images: start dockerd at boot for docker toolsets (fix container-job race) - #1
Merged
Merged
Conversation
…race) Container jobs run `docker version` at job pickup (before any step) to create the job/service containers, so dockerd must be ready the moment the runner accepts a job. The golden previously left docker.service disabled and relied on docker.socket socket-activation, which races under a concurrent matrix: some legs accept a job before docker.socket is up and fail setup with "dial unix /var/run/docker.sock: no such file". For the base/full toolsets (which ship docker) enable docker.service at boot and order firerunner-runner.service After=docker.service via a drop-in. docker.service is Type=notify, so the runner waits until dockerd is READY before accepting a job. The minimal toolset has no docker and keeps docker.service disabled.
There was a problem hiding this comment.
Pull request overview
Starts Docker during boot for Docker-capable Ubuntu images, preventing container-job setup races.
Changes:
- Enables
docker.servicefor base/full toolsets. - Orders the runner after Docker startup.
- Keeps Docker disabled for minimal images.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+301
to
+304
| # base/full start dockerd at boot (runner ordered after it, see DOCKER_BOOT | ||
| # above) so container jobs never race an un-started daemon; minimal keeps docker | ||
| # disabled. The DBs/web servers stay disabled everywhere. Snap, apt timers, | ||
| # networkd-wait-online and other noise are masked outright. |
Member
Author
There was a problem hiding this comment.
Adopted in e0ce8ec — rewrote the boot-policy comment into one consistent paragraph (runner always starts; DBs/web disabled; docker per-toolset: base/full start dockerd at boot and gate the runner behind it, minimal keeps docker disabled).
…cy comment Use Requires= (not Wants=) together with After= so the runner is not started unless docker.service reaches active — otherwise a docker.service failure would still let the runner accept a container job with no daemon, defeating the readiness guarantee. Rewrite the boot-policy comment so it no longer contradicts itself about docker being disabled at boot.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Container jobs (a workflow job with
container:and/orservices:) fail intermittently at job setup on the base/full golden, before any step runs:The GitHub runner runs
docker versionat job pickup (before any step) to create the job container and service containers. So dockerd must be ready the instant the runner accepts the job.The golden currently leaves
docker.servicedisabled and relies ondocker.socketsocket-activation ("start dockerd on firstdockercall"). Under a concurrent matrix this races: some legs accept a job beforedocker.sockethas finished initializing, so/var/run/docker.sockdoesn't exist yet and setup fails. Single/sequential Docker jobs usually win the race, which is why this hides until you run a real matrix.Observed on a real
rails-cimigration (container jobs + Postgres/Redis service containers): with a 4-shard matrix, lint + 2 shards + system-test passed while 2 shards failed at 0.1 min with the error above. Reproducible: single jobs pass, concurrent matrix flakes a subset.Fix
For the toolsets that ship docker (
base/full): start dockerd at boot and order the runner after it.systemctl enable docker.servicefirerunner-runner.service.d/10-docker.conf:After=docker.service+Wants=docker.servicedocker.serviceisType=notify, soAfter=docker.servicemakes the runner wait until dockerd has signalled ready — the runner can never accept a container job before Docker is up. Theminimaltoolset has no docker and keepsdocker.servicedisabled (unchanged).Boot cost is a couple of seconds of dockerd startup on a cold VM, and it's fully hidden by a warm pool (
--min-runners). Non-docker tiers are unaffected.Verification
Generated Dockerfile
RUNline for each toolset:Applied the equivalent patch to a full-docker golden and re-ran the same
rails-cimatrix (lint + 4 shards + system-test, all container jobs with pg/redis services + headless Chromium): all green, no Docker-socket setup failures.