Building WhaleSay with Docker and Gitlab-CI

This describes from start to finish how to configure Gitlab’s continuous integration to build a docker image.

I couldn’t find any simple documentation on what all needs to be setup to build a docker image, so I hope someone finds this useful. I run a rancher cluster, and all my services run on top of this cluster (including gitlab itself). My goal is to describe my infrastructure in various Dockerfiles and configuration files, and have everything automated.

I assume you have Gitlab and Rancher (or other Docker management system) running already.

Step 1 – Setup a Container Registry

The registry requires a key and certificate. The registry.key below should be kept secret, and is only needed by Gitlab.

Run the registry:latest image from the Docker Hub, and mount the certificate from above (registry.crt) and the config.yaml below into /etc/docker/registry/

Note the registry uses Git’s authentication server.

Step 2 – Setup Gitlab

I’m using the excellent Gitlab image from sameersbn. To extend my current gitlab to link with the new registry, add the following to the container settings:

  • A link to the Registry created in step 1 under the name used in the GITLAB_REGISTRY_API_URL, such as “regint” (below)
  • GITLAB_REGISTRY_ENABLED=true
  • GITLAB_REGISTRY_HOST=docker-registry.muzik.ca
  • GITLAB_REGISTRY_KEY_PATH=/path/for/gitlab/to/find/private/key/registry.key
  • GITLAB_REGISTRY_API_URL=http://regint:5000/

This ends up looking like this (Click for a larger image)

Step 3 – Configure Gitlab Runner

From the Gitlab Admin page, choose Overview -> Runners and make note of the Registration token.

Sameersbn’s gitlab-ci-multirunner is missing the docker binaries, which are required for building docker containers inside the multirunner. I’ve extended the multirunner, which is available publicly under mitchese/gitlab-ci-multirunner-docker:latest

This container needs the following environment variables and customizations:

  • An internal service link to the registry, available under “docker”
  • CI_SERVER_URL = https://your.git.server/ci
  • RUNNER_TOKEN = <the token you found in the Gitlab Admin page>
  • RUNNER_DESCRIPTION = a text describing how this should appear in the Gitlab Runners list
  • RUNNER_EXECUTOR = shell
  • Security: Full access to the host
  • Docker socket mounted from the parent system: -v /var/run/docker.sock:/var/run/docker.sock
  • A volume to store permanent data under /home/gitlab_ci_multi_runner/data

 

Last step – tying it all together: WhaleSay

If you’ve made it this far, we have Gitlab setup to use a registry, a runner that is registered with Gitlab — we just need to glue it all together.

Create a new repository and add three files into it. The first two are the Docker examples from WhaleSay:

Dockerfile:

docker.cow

 

.gitlab-ci.yml:

 

In the .gitlab-ci.yml, “#when: manual” is commented out. If this is enabled, commits don’t automatically trigger the build pipeline. Only when you manually start the pipeline will it build the image.  “tags: -dind” is also a selector as to which runner is able to build this project. If you have multiple runners then use tags to bind specific projects with a specific runner (for example, C++ projects with a gcc runner, LaTeX projects with a LaTeX runner, etc).

If all is well, you should have a ready-to-build pipeline (if when:manual was active) or an already built docker image

Clicking the build should result in a successful build:

 

If it does not, you can see the entire build process under the failed job and investigate what is going wrong: