GitLab CI "docker: command not found" in before_script: image debugging
Fixes missing docker CLI in GitLab CI jobs. Use when jobs fail with docker command not found, when choosing between docker-in-docker and socket binding, or when image selection is wrong. Not for docker daemon connection errors.
TL;DR
The job's image simply does not contain the docker CLI: the default images for most jobs have no docker binary. Either use an image with docker installed, install it in before_script, or use the docker-in-docker service properly. Also confirm you actually need the docker CLI: many "docker build" steps are better as kaniko or buildah jobs that never needed docker at all.
The query
GitLab CI "docker: command not found" in before_script: image debuggingUse this when
- Jobs fail with docker: command not found
- Choosing docker-in-docker vs socket binding
- before_script assumes tools the image lacks
- Migrating jobs between images
Not for when
- Cannot connect to the docker daemon (CLI exists, daemon missing)
- Docker build failures (the CLI works, the build fails)
- Registry authentication
Steps
Step 1: Check what the image actually contains
Inspect the job's image: does it ship a docker CLI. Most language images do not. The fix starts from knowing the image contents, not from assuming. Expected output: the image's toolset known; docker confirmed absent.
Step 2: Use a docker-capable image or install the CLI
Switch the job to an image containing the docker CLI, or install it in before_script from the official static binaries. Installing per-job is slower but keeps your preferred base image. Expected output: the docker CLI available in the job environment.
Step 3: Decide: DinD service vs host socket
If you need to build images, add the docker:dind service and configure the client to talk to it, or bind-mount the host's docker socket (simpler, but the builds share the host daemon with security implications). Choose deliberately per runner type. Expected output: a working docker daemon reachable from the job.
Step 4: Consider daemonless builders instead
For image builds, kaniko or buildah run without a docker daemon at all and sidestep the entire DinD complexity. If the job only builds and pushes, you may not need docker whatsoever. Expected output: the job building images without docker-in-docker.
Step 5: Pin the builder image version
Whether docker image or kaniko, pin the version. "Latest" builder images change behavior under you; pinned builders make the pipeline reproducible. Expected output: deterministic builder tooling.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_ahQK6NMFyhTBn6IoEzNIWg
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.