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.
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
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
Edit the file, and add:
image = "docker:dind" privileged = true pull_policy = "if-not-present"
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]