I have a GitLab CI/CD pipeline that is being run on GKE.
One of the jobs in the pipeline uses a Docker-in-Docker service container so that Docker commands can be run inside the job container:
my_job:
image: docker:20.10.7
services:
- docker:dind
script:
- docker login -u $USER -p $PASSWORD $REGISTRY
- docker pull ${REGISTRY}:$TAG
# ...more Docker commands
It all works fine, but I would like to know why. How does the Docker client in the my_job
container know that it needs to communicate with the Docker daemon running inside the Docker-in-Docker service container, and how does it know the host and port of this daemon?
There is no 'discovery' process, really. The docker client must be told about the daemon host through configuration (e.g., DOCKER_HOST
). Otherwise, the client will assume a default configuration:
DOCKER_HOST
configuration is present, this is used. Otherwise:unix:///var/run/docker.sock
) is present, the default socket is used.tcp://docker:2375
is usedtcp://docker:2376
is usedYou can see this logic explicitly in the docker
dockerfile entrypoint.
The docker client can be configured a couple ways, but the most common way in GitLab CI and with the official docker
image is through the DOCKER_HOST
environment variable. If you don't see this variable in your YAML, it may be set as a project or group setting or may be set on the runner configuration, or is relying on default behavior described above.
It's also possible, depending on your runner configuration (config.toml
), that your job is not using the docker:dind
service daemon at all. For example, if your runner has a volumes
specification mounting the docker socket (/var/run/docker.sock
) into the job container and there is no DOCKER_HOST
(or equivalent) configuration, then your job is probably not even using the service because it would use the mounted socket (per the configuration logic above). You can run docker info
in your job to be sure of this one way or the other.
Additional references: