Quite a while ago I started to use the Giblab CI. Although you find plenty of good pre-build container images on DockerHub, I sometimes want to have my very own images.

One of the use cases is have a container for testing scripts that use additional libraries. I have some Perl scripts that I build using Dist::Zilla. Since it takes quite a while to install it in the default Perl container which quite extends the build time, I want to have it pre-installed in a container.

Therefore I use the Docker registry built into Gitlab. The challenge is to get the container build and upload into the registry up and running. It took me quite a while to put everything in place…

My workflow uses the Docker-in-Docker build to create the container and upload them to Gitlab’s registry. To be able to test against severyl Perl version, I created branches for the wanted versions.

The .gitlab-ci.yml file looks like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
image: docker:git

services:
  - docker:dind

stages:
- build
- release

variables:
  CONTAINER_TEST_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME-test
  CONTAINER_RELEASE_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME

before_script:
  - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY

build:
  stage: build
  script:
    - docker build -t $CONTAINER_TEST_IMAGE .
    - docker push $CONTAINER_TEST_IMAGE
  tags:
    - container

release-image:
  stage: release
  script:
    - docker pull $CONTAINER_TEST_IMAGE
    - docker tag $CONTAINER_TEST_IMAGE $CONTAINER_RELEASE_IMAGE
    - docker push $CONTAINER_RELEASE_IMAGE
  only:
    - $CI_COMMIT_REF_NAME
  tags:
    - container

Gitlab CI offers some useful variables that can be used within the CI script. These make it fairly easy to build and tag the container image. The
Gitlab variables documentation gives a good overview.

There are two points worth mentioning. The point onlyand tags. With only it’s possible to restrict the build, in this case to the branch we’ve committed to. But there are a lot more options which you can see in the CI yaml description.

With the tags option it’s possible to select specific runners for the build. Since you can use several runners on the same machine or a runner on a complete different machine the concept is very convenient. If you want to test Powershell scripts for example you surely want to run it on a Windows machine. So you setup a tagged runner on a Windows machine and register it with your Gitlab instance. And that’s it…

So one the last step is to create and register a Docker-in-Docker enabled runner that uses the specified tag.

This is done with the following command line

1
2
3
4
5
6
7
8
gitlab-ci-multi-runner register -n \
  --url GITLAB_URL \
  --registration-token REGISTRATION_TOKEN \
  --executor docker \
  --name image-creation-runner \
  --docker-image "docker:latest" \
  --docker-privileged \
  --tag-list container

You could define the runner directly in the configuration file, but unfortunately it’s not possible to add tags there… The registration token and gitlab url can be read in the projects settings at the CI/CD site.

Now everything is in place and after pushing your project to Gitlab the build pipeline starts. If the build was successfull it is uploaded to the internal registry. Now the container is waiting to be used…