Auto-derive docker daemon access for plugins that require it (drop manual `docker: true` for buildx)
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 7
- Forks
- 3
- Avg merge
- 2h 12m
- Merged PRs (30d)
- 30
Description
Problem
A job that uses: the buildx plugin (and any future plugin that needs a docker daemon) must also remember to set docker: true on the job. Forgetting it produces a confusing, slow failure — the plugin waits 60s for a daemon that never comes up:
gocdnext/buildx: docker daemon did not become reachable within 60s
DOCKER_HOST=<unset>
is `docker: true` set on the job? agent wires a DinD sidecar only then
── task failed after 1m2s (exit 2)
buildx is useless without a daemon — it can't do anything else. The plugin already knows it needs docker, so requiring the pipeline author to repeat that as docker: true is redundant and a footgun (hit in real use on a release pipeline).
Why the flag must still exist (do NOT make it a global default)
docker: true is not free, and its cost/risk differs per engine:
| Engine | docker: true does… |
Cost / risk | Without it |
|---|---|---|---|
Docker (agent/internal/engine/docker.go:24-28) |
bind-mounts host /var/run/docker.sock + sets DOCKER_HOST |
cheap, but "effectively root on the host via the Docker API" (per the code comment) | no socket → buildx fails |
K8s (agent/internal/engine/kubernetes_isolated.go:317-357) |
spins up a privileged DinD sidecar (privileged: true, full second daemon) |
heavy + privileged | no daemon reachable (nodes run containerd, not docker) → buildx fails |
So most jobs (npm, go test, trivy) must NOT get a daemon by default — especially under k8s where it means a privileged container. The flag stays as the explicit opt-in for raw image: jobs that need a daemon (e.g. testcontainers, ad-hoc docker build).
Proposal
Let a plugin declare its requirement in its manifest, and have the agent satisfy it the engine-appropriate way — so the author never writes docker: true for such plugins:
plugin.yamlschema: addrequires_docker: true(todaydocker: trueonly appears in the example snippets of the manifest, there is no capability field). Mirror it as an OCI image label so the image is self-describing.- Resolution (prefer parse-time, via embedded catalog): the server embeds the plugin catalog (
go:embed); at parse/apply, a job using a docker-requiring catalog plugin auto-setsDocker=true, and we log it (job Y: docker access auto-enabled, required by plugin buildx) so the privileged-sidecar decision is traceable, not a hidden default. Custom/out-of-catalog plugins keep the current clear runtime error (or fall back to an agent-side image-label read if we want full generality — tradeoff: extra registry round-trip + private-registry creds at scheduling time). - The agent then wires the daemon per engine (socket-mount on docker, DinD sidecar on k8s) exactly as it does today for
docker: true— no change to the low-level path.
Decisions to keep
docker: truestays valid and explicit for raw jobs and custom plugins; auto-derive only adds a path, never removes the knob.- Never a global default-on (security + cost, especially privileged DinD under k8s).
- Auto-enable is logged at apply so it's auditable.
Out of scope / open questions
- Parse-time embedded-catalog vs agent-time image-label read (generality vs cost) — pick during design.
- Whether to fail loud at apply ("buildx requires docker access") instead of silently auto-enabling — leaning auto-enable+log since choosing buildx is itself the opt-in, but worth deciding.
Context
Surfaced while validating the gated delivery flow in an internal test repo: the release pipeline's buildx build jobs failed for exactly this reason. Immediate fix was adding docker: true explicitly; this issue tracks removing the footgun in core.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the plugin.yaml manifest examples and the engine paths in agent/internal/engine/docker.go and agent/internal/engine/kubernetes_isolated.go. Then trace the server's embedded plugin catalog and job parse/apply flow to decide where requires_docker is resolved and logged. Done means catalog plugins can declare the requirement while raw jobs and custom plugins retain explicit docker access behavior, with tests covering both engines and no global default.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, go, kubernetes
- Domain
- ci-cd, devops, infrastructure
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100