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 <zettat123@gmail.com>
Co-committed-by: Zettat123 <zettat123@gmail.com>
This commit is contained in:
Zettat123 2023-06-30 04:00:04 +00:00 committed by Jason Song
parent b0bd503b11
commit ccc27329dc
4 changed files with 62 additions and 29 deletions

View File

@ -63,9 +63,28 @@ func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command,
} }
if ls.RequireDocker() { if ls.RequireDocker() {
if err := envcheck.CheckIfDockerRunning(ctx, cfg); err != nil { dockerSocketPath, err := getDockerSocketPath(cfg.Container.DockerHost)
if err != nil {
return err 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( 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")
}

View File

@ -179,27 +179,28 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
BindWorkdir: false, BindWorkdir: false,
ActionCacheDir: filepath.FromSlash(r.cfg.Host.WorkdirParent), ActionCacheDir: filepath.FromSlash(r.cfg.Host.WorkdirParent),
ReuseContainers: false, ReuseContainers: false,
ForcePull: false, ForcePull: false,
ForceRebuild: false, ForceRebuild: false,
LogOutput: true, LogOutput: true,
JSONLogger: false, JSONLogger: false,
Env: r.envs, Env: r.envs,
Secrets: task.Secrets, Secrets: task.Secrets,
GitHubInstance: strings.TrimSuffix(r.client.Address(), "/"), GitHubInstance: strings.TrimSuffix(r.client.Address(), "/"),
AutoRemove: true, AutoRemove: true,
NoSkipCheckout: true, NoSkipCheckout: true,
PresetGitHubContext: preset, PresetGitHubContext: preset,
EventJSON: string(eventJSON), EventJSON: string(eventJSON),
ContainerNamePrefix: fmt.Sprintf("GITEA-ACTIONS-TASK-%d", task.Id), ContainerNamePrefix: fmt.Sprintf("GITEA-ACTIONS-TASK-%d", task.Id),
ContainerMaxLifetime: maxLifetime, ContainerMaxLifetime: maxLifetime,
ContainerNetworkMode: container.NetworkMode(r.cfg.Container.Network), ContainerNetworkMode: container.NetworkMode(r.cfg.Container.Network),
ContainerOptions: r.cfg.Container.Options, ContainerOptions: r.cfg.Container.Options,
Privileged: r.cfg.Container.Privileged, ContainerDaemonSocket: r.cfg.Container.DockerHost,
DefaultActionsURLs: parseDefaultActionsURLs(taskContext["gitea_default_actions_url"].GetStringValue()), Privileged: r.cfg.Container.Privileged,
PlatformPicker: r.labels.PickPlatform, DefaultActionsURLs: parseDefaultActionsURLs(taskContext["gitea_default_actions_url"].GetStringValue()),
Vars: task.Vars, PlatformPicker: r.labels.PickPlatform,
ValidVolumes: r.cfg.Container.ValidVolumes, Vars: task.Vars,
ValidVolumes: r.cfg.Container.ValidVolumes,
} }
rr, err := runner.New(runnerConfig) rr, err := runner.New(runnerConfig)

View File

@ -69,8 +69,9 @@ container:
# - '**' # - '**'
valid_volumes: [] valid_volumes: []
# overrides the docker client host with the specified one. # overrides the docker client host with the specified one.
# default value is the value of DOCKER_HOST environment variable. # If it's empty, act_runner will find an available docker host automatically.
# if DOCKER_HOST is not set, the default value is unix:///var/run/docker.sock # 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: "" docker_host: ""
host: host:

View File

@ -8,17 +8,15 @@ import (
"fmt" "fmt"
"github.com/docker/docker/client" "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{ opts := []client.Opt{
client.FromEnv, client.FromEnv,
} }
if cfg.Container.DockerHost != "" { if configDockerHost != "" {
opts = append(opts, client.WithHost(cfg.Container.DockerHost)) opts = append(opts, client.WithHost(configDockerHost))
} }
cli, err := client.NewClientWithOpts(opts...) cli, err := client.NewClientWithOpts(opts...)