DEV Community

DevOps Start
DevOps Start

Posted on • Originally published at devopsstart.com

Fix GitLab CI Docker daemon connection error in 3 steps

This article was originally published on DevOpsStart.com. Here's a quick fix for the dreaded 'Cannot connect to the Docker daemon' error in GitLab CI.

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?
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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: ""
Enter fullscreen mode Exit fullscreen mode

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 .
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Look for lines like:

Starting container service-docker:dind-0 ... 
Enter fullscreen mode Exit fullscreen mode

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:dind to any job that needs docker commands.
  • Always set DOCKER_HOST: tcp://docker:2375 as a top-level variable in your pipeline.
  • Verify your GitLab Runner's config.toml has privileged = true before you push new jobs.
  • For a production-grade setup, consider using the docker:24.0.7-dind image variant. It bundles the daemon and the client in one image, reducing the chance of version mismatches.

Top comments (0)