How to set up Docker in Docker¶
Some projects create their own Docker containers, stored in the GitLab container registry which they use for build and test. This speeds up pipelines, because each pipeline job no longer needs to install its own OS packages.
Modifying .gitlab-ci.yml¶
Many Beautiful Canoe repositories follow the recipe here.
First, we create a new directory .meta
at the top-level of the repository, and place a Dockerfile
in that directory.
Next, add a new stage to the pipeline:
stages:
- prepare
- ...
Then add a new job to the pipeline to build the Docker container and upload it to the GitLab container registry:
meta-build-image:
stage: prepare
image: docker:stable
variables:
DOCKER_TLS_CERTDIR: ""
services:
- docker:dind
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- cd .meta
- docker build -t $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/CONTAINERNAME:latest .
- docker push $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/CONTAINERNAME:latest
only:
changes:
- .meta/Dockerfile
tags:
- dind
Note that we only build the Docker container when the Dockerfile
has changed, and the container we push is tagged as the latest container no matter which branch the container was built on.
You may wish to tweak this, for example to only build the Dockerfile
on the develop
branch:
only:
develop
changes:
- .meta/Dockerfile
Lastly, change the other CI jobs to use the new container:
...
image: registry.gitlab.com/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/CONTAINERNAME
...
Modify the gitlab-runner configuration¶
Due to the way Docker supports TLS, if you are running the prepare
CI job on Beautiful Canoe servers, you will need to tweak the config.toml
for your runner.
Firstly, create a new runner, tagged with dind
that will only be used for building container images in your repository.
Next, locate the config.toml
file for that runner.
It is likely to be either in /etc/gitlab-runner/config.toml
if you are running gitlab-runner
as root, or /home/gitlab-runner/.gitlab-runner/config.toml
if you are running the service as gitlab-runner
.
Edit the file, and add:
image = "docker:dind"
privileged = true
pull_policy = "if-not-present"
to the runners.docker
configuration.
The first two lines there fix the TLS support issues (by disabling TLS support).
The last line pull_policy ...
ensures that Docker will use a docker:dine
image held locally on the server, if there is one.
Your runner should look something like this:
[[runners]]
name = "RUNNER-NAME"
url = "https://gitlab.com/"
token = "TOKEN"
executor = "docker"
[runners.custom_build_dir]
[runners.docker]
tls_verify = false
image = "docker:dind"
privileged = true
disable_entrypoint_overwrite = false
oom_kill_disable = false
pull_policy = "if-not-present"
disable_cache = false
volumes = ["/cache"]
shm_size = 0
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]