From ccc27329dc604cc2d38a5449977d5c379c6ac298 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Fri, 30 Jun 2023 04:00:04 +0000 Subject: [PATCH] Improve the usage of `docker_host` configuration (#260) Follow #242, #244 Fixes #258 Users could use `docker_host` configuration to specify which docker daemon will be used by act_runner. - If `docker_host` is **empty**, act_runner will find an available docker host automatically. - If `docker_host` is **"-"**, act_runner will find an available docker host automatically, but the docker host won't be mounted to the job containers and service containers. - If `docker_host` is **not empty or "-"**, the specified docker host will be used. An error will be returned if it doesn't work. Reviewed-on: https://gitea.com/gitea/act_runner/pulls/260 Co-authored-by: Zettat123 Co-committed-by: Zettat123 --- internal/app/cmd/daemon.go | 35 +++++++++++++++++++- internal/app/run/runner.go | 43 +++++++++++++------------ internal/pkg/config/config.example.yaml | 5 +-- internal/pkg/envcheck/docker.go | 8 ++--- 4 files changed, 62 insertions(+), 29 deletions(-) diff --git a/internal/app/cmd/daemon.go b/internal/app/cmd/daemon.go index aebe641..05c80a2 100644 --- a/internal/app/cmd/daemon.go +++ b/internal/app/cmd/daemon.go @@ -63,9 +63,28 @@ func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command, } if ls.RequireDocker() { - if err := envcheck.CheckIfDockerRunning(ctx, cfg); err != nil { + dockerSocketPath, err := getDockerSocketPath(cfg.Container.DockerHost) + if err != nil { return err } + if err := envcheck.CheckIfDockerRunning(ctx, dockerSocketPath); err != nil { + return err + } + // if dockerSocketPath passes the check, override DOCKER_HOST with dockerSocketPath + os.Setenv("DOCKER_HOST", dockerSocketPath) + // empty cfg.Container.DockerHost means act_runner need to find an available docker host automatically + // and assign the path to cfg.Container.DockerHost + if cfg.Container.DockerHost == "" { + cfg.Container.DockerHost = dockerSocketPath + } + // check the scheme, if the scheme is not npipe or unix + // set cfg.Container.DockerHost to "-" because it can't be mounted to the job conatiner + if protoIndex := strings.Index(cfg.Container.DockerHost, "://"); protoIndex != -1 { + scheme := cfg.Container.DockerHost[:protoIndex] + if !strings.EqualFold(scheme, "npipe") && !strings.EqualFold(scheme, "unix") { + cfg.Container.DockerHost = "-" + } + } } cli := client.New( @@ -140,3 +159,17 @@ func initLogging(cfg *config.Config) { } } } + +func getDockerSocketPath(configDockerHost string) (string, error) { + // a `-` means don't mount the docker socket to job containers + if configDockerHost != "" && configDockerHost != "-" { + return configDockerHost, nil + } + + socket, found := os.LookupEnv("DOCKER_HOST") + if found { + return socket, nil + } + + return "", fmt.Errorf("daemon Docker Engine socket not found and docker_host config was invalid") +} diff --git a/internal/app/run/runner.go b/internal/app/run/runner.go index b4b0487..2f40a05 100644 --- a/internal/app/run/runner.go +++ b/internal/app/run/runner.go @@ -179,27 +179,28 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report. BindWorkdir: false, ActionCacheDir: filepath.FromSlash(r.cfg.Host.WorkdirParent), - ReuseContainers: false, - ForcePull: false, - ForceRebuild: false, - LogOutput: true, - JSONLogger: false, - Env: r.envs, - Secrets: task.Secrets, - GitHubInstance: strings.TrimSuffix(r.client.Address(), "/"), - AutoRemove: true, - NoSkipCheckout: true, - PresetGitHubContext: preset, - EventJSON: string(eventJSON), - ContainerNamePrefix: fmt.Sprintf("GITEA-ACTIONS-TASK-%d", task.Id), - ContainerMaxLifetime: maxLifetime, - ContainerNetworkMode: container.NetworkMode(r.cfg.Container.Network), - ContainerOptions: r.cfg.Container.Options, - Privileged: r.cfg.Container.Privileged, - DefaultActionsURLs: parseDefaultActionsURLs(taskContext["gitea_default_actions_url"].GetStringValue()), - PlatformPicker: r.labels.PickPlatform, - Vars: task.Vars, - ValidVolumes: r.cfg.Container.ValidVolumes, + ReuseContainers: false, + ForcePull: false, + ForceRebuild: false, + LogOutput: true, + JSONLogger: false, + Env: r.envs, + Secrets: task.Secrets, + GitHubInstance: strings.TrimSuffix(r.client.Address(), "/"), + AutoRemove: true, + NoSkipCheckout: true, + PresetGitHubContext: preset, + EventJSON: string(eventJSON), + ContainerNamePrefix: fmt.Sprintf("GITEA-ACTIONS-TASK-%d", task.Id), + ContainerMaxLifetime: maxLifetime, + ContainerNetworkMode: container.NetworkMode(r.cfg.Container.Network), + ContainerOptions: r.cfg.Container.Options, + ContainerDaemonSocket: r.cfg.Container.DockerHost, + Privileged: r.cfg.Container.Privileged, + DefaultActionsURLs: parseDefaultActionsURLs(taskContext["gitea_default_actions_url"].GetStringValue()), + PlatformPicker: r.labels.PickPlatform, + Vars: task.Vars, + ValidVolumes: r.cfg.Container.ValidVolumes, } rr, err := runner.New(runnerConfig) diff --git a/internal/pkg/config/config.example.yaml b/internal/pkg/config/config.example.yaml index e71184b..773fd20 100644 --- a/internal/pkg/config/config.example.yaml +++ b/internal/pkg/config/config.example.yaml @@ -69,8 +69,9 @@ container: # - '**' valid_volumes: [] # overrides the docker client host with the specified one. - # default value is the value of DOCKER_HOST environment variable. - # if DOCKER_HOST is not set, the default value is unix:///var/run/docker.sock + # If it's empty, act_runner will find an available docker host automatically. + # If it's "-", act_runner will find an available docker host automatically, but the docker host won't be mounted to the job containers and service containers. + # If it's not empty or "-", the specified docker host will be used. An error will be returned if it doesn't work. docker_host: "" host: diff --git a/internal/pkg/envcheck/docker.go b/internal/pkg/envcheck/docker.go index af7fe97..0a634ad 100644 --- a/internal/pkg/envcheck/docker.go +++ b/internal/pkg/envcheck/docker.go @@ -8,17 +8,15 @@ import ( "fmt" "github.com/docker/docker/client" - - "gitea.com/gitea/act_runner/internal/pkg/config" ) -func CheckIfDockerRunning(ctx context.Context, cfg *config.Config) error { +func CheckIfDockerRunning(ctx context.Context, configDockerHost string) error { opts := []client.Opt{ client.FromEnv, } - if cfg.Container.DockerHost != "" { - opts = append(opts, client.WithHost(cfg.Container.DockerHost)) + if configDockerHost != "" { + opts = append(opts, client.WithHost(configDockerHost)) } cli, err := client.NewClientWithOpts(opts...)