Fix GitLab CI Docker daemon connection error in 3 steps
Fix the 'Cannot connect to the Docker daemon at' error in GitLab CI. Learn to add docker:dind service, set DOCKER_HOST, and enable privileged mode for reliable...
The Problem
You have a GitLab CI job that tries to run docker build or docker info, and it fails with this error:
Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?
The error means your job is running inside a container that has the docker CLI installed but no Docker daemon (dockerd) service to talk to. The default docker image from Docker Hub ships only the client. Without a running daemon, every docker command returns this error.
Root Causes
Three things cause this error.
1. Missing docker service in .gitlab-ci.yml
You must define a services block that runs the daemon. The standard approach is:
services:
- docker:dind
Without this, your job has no daemon to connect to.
2. Incorrect or missing DOCKER_HOST variable
When you use the docker executor (the default GitLab Runner executor), the daemon runs as a separate container in the same Pod. You must tell the client where to find it:
variables:
DOCKER_HOST: tcp://docker:2375
If DOCKER_HOST is set to tcp://localhost:2375 or missing entirely, the client looks for a local Unix socket that does not exist inside your job container. The job container has no socket file.
3. Runner not in privileged mode
The docker:dind service requires privileged mode to run its own Docker daemon. If your GitLab Runner’s config.toml has privileged = false or is unset, the dind container cannot start. Check your runner configuration:
$ cat /etc/gitlab-runner/config.toml
[[runners]]
name = "my-runner"
url = "https://gitlab.com/"
token = "..."
executor = "docker"
[runners.docker]
privileged = true
pull_policy = "always"
If privileged is false or absent, the dind service never boots, and you get the Cannot connect to the Docker daemon error.
The Solution
A complete fix takes three steps.
Step 1: add the docker:dind service
Add this to your .gitlab-ci.yml:
image: docker:24.0.7
services:
- name: docker:dind
alias: docker
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
The DOCKER_HOST value tcp://docker:2375 tells the client to use the service container named docker (the GitLab Runner resolves the service alias to the container hostname). The DOCKER_TLS_CERTDIR: "" disables TLS for simplicity.
Step 2: test with a simple job
Add a minimal job to verify the fix works:
build:
stage: build
script:
- docker info
- docker build -t my-app .
The docker info command confirms the daemon is reachable. If it succeeds, your pipeline is ready.
Step 3: check runner logs
If docker info still fails, inspect the runner logs. On your GitLab Runner host, run:
$ docker logs <runner-container-id> --tail 50
Look for lines like:
Starting container service-docker:dind-0 ...
If you see no such line, the service never started. Check privileged mode again in config.toml.
Prevention
To avoid this error in future:
- Always add
services: - docker:dindto any job that needsdockercommands. - Always set
DOCKER_HOST: tcp://docker:2375as a top-level variable in your pipeline. - Verify your GitLab Runner’s
config.tomlhasprivileged = truebefore you push new jobs. - For a production-grade setup, consider using the
docker:24.0.7-dindimage variant. It bundles the daemon and the client in one image, reducing the chance of version mismatches.
Get the next article in your inbox
Practical DevOps tips, tutorials, and guides. No spam, unsubscribe anytime.