mirror of
https://gitea.com/gitea/runner.git
synced 2026-11-14 03:43:42 +00:00
fix: make container.sweep opt-in (#1389)
Sweeping removed every container a job started through its Docker proxy, which silently tore down services that jobs deploy to the runner's own Docker daemon. Deploying from a runner on the target host is common, so `container.sweep` now defaults to `false` and CI-only runners can opt in with `container.sweep: true`. Fixes https://gitea.com/gitea/runner/issues/1385 Reviewed-on: https://gitea.com/gitea/runner/pulls/1389 Reviewed-by: bircni <[email protected]> Co-authored-by: silverwind <[email protected]>
This commit is contained in:
1 parent
95ef17d022
commit
bb6d793cb9
8 files changed
+9
-8
No files matched your search
@@ -243,7 +243,7 @@ volumes:
|
|||||||
- ${GITEA_DOCKER_WORKSPACE:-.}/data:/app/data
|
- ${GITEA_DOCKER_WORKSPACE:-.}/data:/app/data
|
||||||
```
|
```
|
||||||
|
|
||||||
In most Linux container jobs, the containers, networks and volumes a job creates are removed when it ends, `docker compose` services included. Set `container.sweep: false` if jobs deploy services to the runner's Docker daemon.
|
Set `container.sweep: true` to remove the containers, networks and volumes most Linux container jobs create when they end, `docker compose` services included. Leave it off if jobs deploy services to the runner's Docker daemon.
|
||||||
|
|
||||||
### Built-in actions (`uses: builtin:<name>`)
|
### Built-in actions (`uses: builtin:<name>`)
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ func TestDockerProxyMountedJob(t *testing.T) {
|
|||||||
ContainerNamePrefix: resourceName,
|
ContainerNamePrefix: resourceName,
|
||||||
ContainerDaemonSocket: dockerClient.DaemonHost(),
|
ContainerDaemonSocket: dockerClient.DaemonHost(),
|
||||||
ContainerMaxLifetime: 2 * time.Minute,
|
ContainerMaxLifetime: 2 * time.Minute,
|
||||||
|
Sweep: true,
|
||||||
ContainerOptions: "-v /usr/local/bin/docker:/usr/local/bin/docker:ro -v /usr/local/libexec/docker/cli-plugins:/usr/local/libexec/docker/cli-plugins:ro",
|
ContainerOptions: "-v /usr/local/bin/docker:/usr/local/bin/docker:ro -v /usr/local/libexec/docker/cli-plugins:/usr/local/libexec/docker/cli-plugins:ro",
|
||||||
ValidVolumes: []string{"/usr/local/bin/docker", "/usr/local/libexec/docker/cli-plugins"},
|
ValidVolumes: []string{"/usr/local/bin/docker", "/usr/local/libexec/docker/cli-plugins"},
|
||||||
Env: map[string]string{"PROXY_TEST_RESOURCE": resourceName, "PROXY_TEST_MODE": mode, "PROXY_TEST_IMAGE": baseImage, "COMPOSE_PROJECT_NAME": resourceName},
|
Env: map[string]string{"PROXY_TEST_RESOURCE": resourceName, "PROXY_TEST_MODE": mode, "PROXY_TEST_IMAGE": baseImage, "COMPOSE_PROJECT_NAME": resourceName},
|
||||||
|
|||||||
@@ -810,7 +810,7 @@ func (rc *RunContext) cleanupJobResources(networkName string, createAndDeleteNet
|
|||||||
errs = append(errs, runAll(ctx, containers))
|
errs = append(errs, runAll(ctx, containers))
|
||||||
ctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), jobCleanupTimeout)
|
ctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), jobCleanupTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
if !common.Dryrun(ctx) && !rc.Config.NoSweep && (preclean || rc.hadDockerProxy) {
|
if !common.Dryrun(ctx) && rc.Config.Sweep && (preclean || rc.hadDockerProxy) {
|
||||||
errs = append(errs, container.RemoveDockerJobResources(ctx, rc.jobContainerName())) // after the containers, whose endpoints would block removing the job networks
|
errs = append(errs, container.RemoveDockerJobResources(ctx, rc.jobContainerName())) // after the containers, whose endpoints would block removing the job networks
|
||||||
}
|
}
|
||||||
var rest []common.Executor
|
var rest []common.Executor
|
||||||
|
|||||||
@@ -725,7 +725,7 @@ func TestCleanupJobResources(t *testing.T) {
|
|||||||
service.On("Remove").Return(removeAlongside(serviceRemoving, jobRemoving, removeError)).Once()
|
service.On("Remove").Return(removeAlongside(serviceRemoving, jobRemoving, removeError)).Once()
|
||||||
service.On("Close").Return(func(context.Context) error { return closeError }).Once()
|
service.On("Close").Return(func(context.Context) error { return closeError }).Once()
|
||||||
rc := &RunContext{
|
rc := &RunContext{
|
||||||
Config: &Config{CacheContainer: "cache-container", NoSweep: name == "kept proxy"},
|
Config: &Config{CacheContainer: "cache-container", Sweep: name != "kept proxy"},
|
||||||
Run: &model.Run{Workflow: &model.Workflow{Name: "wf"}, JobID: "job"},
|
Run: &model.Run{Workflow: &model.Workflow{Name: "wf"}, JobID: "job"},
|
||||||
JobContainer: job,
|
JobContainer: job,
|
||||||
serviceContainers: []*serviceContainer{{name: "svc", container: service}},
|
serviceContainers: []*serviceContainer{{name: "svc", container: service}},
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ type Config struct {
|
|||||||
MaxParallel int // max parallel jobs to run across all workflows (0 = no limit, uses CPU count)
|
MaxParallel int // max parallel jobs to run across all workflows (0 = no limit, uses CPU count)
|
||||||
AllocatePTY bool // allocate a pseudo-TTY for each step's process
|
AllocatePTY bool // allocate a pseudo-TTY for each step's process
|
||||||
ServiceReadyTimeout time.Duration // how long a job waits for its service containers to report healthy (0 uses the default)
|
ServiceReadyTimeout time.Duration // how long a job waits for its service containers to report healthy (0 uses the default)
|
||||||
NoSweep bool // keep the containers, networks and volumes a job creates through its docker proxy
|
Sweep bool // remove the containers, networks and volumes a job creates through its docker proxy
|
||||||
RunnerName string // name this runner registered with, reported as `runner.name`, defaults to the hostname
|
RunnerName string // name this runner registered with, reported as `runner.name`, defaults to the hostname
|
||||||
JobStartedHook string // script run inside the job environment before the job's first step; ACTIONS_RUNNER_HOOK_JOB_STARTED is read from Env when empty
|
JobStartedHook string // script run inside the job environment before the job's first step; ACTIONS_RUNNER_HOOK_JOB_STARTED is read from Env when empty
|
||||||
JobCompletedHook string // script run inside the job environment after the job's last step; ACTIONS_RUNNER_HOOK_JOB_COMPLETED is read from Env when empty
|
JobCompletedHook string // script run inside the job environment after the job's last step; ACTIONS_RUNNER_HOOK_JOB_COMPLETED is read from Env when empty
|
||||||
|
|||||||
@@ -612,7 +612,7 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
|||||||
},
|
},
|
||||||
ContainerOptions: r.cfg.Container.Options,
|
ContainerOptions: r.cfg.Container.Options,
|
||||||
ServiceReadyTimeout: r.cfg.Container.ServiceReadyTimeout,
|
ServiceReadyTimeout: r.cfg.Container.ServiceReadyTimeout,
|
||||||
NoSweep: r.cfg.Container.Sweep != nil && !*r.cfg.Container.Sweep,
|
Sweep: r.cfg.Container.Sweep,
|
||||||
ContainerDaemonSocket: r.cfg.Container.DockerHost,
|
ContainerDaemonSocket: r.cfg.Container.DockerHost,
|
||||||
Privileged: r.cfg.Container.Privileged,
|
Privileged: r.cfg.Container.Privileged,
|
||||||
DefaultActionInstance: r.getDefaultActionsURL(task),
|
DefaultActionInstance: r.getDefaultActionsURL(task),
|
||||||
|
|||||||
@@ -306,8 +306,8 @@ container:
|
|||||||
# healthy. A negative value (e.g. -1s) starts the steps without waiting.
|
# healthy. A negative value (e.g. -1s) starts the steps without waiting.
|
||||||
#service_ready_timeout: 5m
|
#service_ready_timeout: 5m
|
||||||
# Remove the containers, networks and volumes a job creates through its Docker proxy when
|
# Remove the containers, networks and volumes a job creates through its Docker proxy when
|
||||||
# the job ends. Set to false when jobs deploy services to the runner's Docker daemon.
|
# the job ends. Leave off when jobs deploy services to the runner's Docker daemon.
|
||||||
#sweep: true
|
#sweep: false
|
||||||
|
|
||||||
host:
|
host:
|
||||||
# The parent directory of a job's working directory.
|
# The parent directory of a job's working directory.
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ type Container struct {
|
|||||||
DockerTimeout time.Duration `yaml:"docker_timeout"` // Timeout to wait for the docker daemon to be reachable, if docker is required by require_docker or runner
|
DockerTimeout time.Duration `yaml:"docker_timeout"` // Timeout to wait for the docker daemon to be reachable, if docker is required by require_docker or runner
|
||||||
BindWorkdir bool `yaml:"bind_workdir"` // BindWorkdir mounts the workspace from a host directory instead of a Docker volume.
|
BindWorkdir bool `yaml:"bind_workdir"` // BindWorkdir mounts the workspace from a host directory instead of a Docker volume.
|
||||||
ServiceReadyTimeout time.Duration `yaml:"service_ready_timeout"` // ServiceReadyTimeout bounds how long a job waits for a service container that declares a healthcheck to report healthy. Negative disables waiting.
|
ServiceReadyTimeout time.Duration `yaml:"service_ready_timeout"` // ServiceReadyTimeout bounds how long a job waits for a service container that declares a healthcheck to report healthy. Negative disables waiting.
|
||||||
Sweep *bool `yaml:"sweep"` // Sweep removes the containers, networks and volumes a job creates through its Docker proxy when the job ends. Unset means enabled.
|
Sweep bool `yaml:"sweep"` // Sweep removes the containers, networks and volumes a job creates through its Docker proxy when the job ends.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values of Runner.ToolCacheMode: the runner mounts no tool cache, or one that every job reuses.
|
// Values of Runner.ToolCacheMode: the runner mounts no tool cache, or one that every job reuses.
|
||||||
|
|||||||
Reference in new issue
Block a user