Building container images with Gitlab CI
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
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 only
and 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
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 successful it is uploaded to the internal registry. Now the container is waiting to be used…