Tech Blog.

Thoughts, stories, ideas.

GitLab CI

10. September 2017

In this two-part article, we will take a closer look at the continuous integration functionalities of GitLab CI.

The first part deals with installation and configuration, while the second part provides more detailed information on individual application scenarios.

What does CI actually mean?

In this case, CI stands for continuous integration. But simply, this means that a script is executed after every change to the source code of a project.
The CI script is triggered through a version control system in most cases. Files created by this script can later be reused as so-called build artifacts.

In many cases, this script starts unit tests, which check whether the changes that were just implemented do not have an unintentional effect on other parts of the project.
But unit tests are only one scenario, a CI can also, for example, build packages, create documentation or even deploy applications.

GitLab CI

GitLab is an open source solution for git hosting, which also offers CI functionality, among others. Starting with version 8.2, the CI part has been tightly integrated in GitLab and no longer needs to be installed on a separate server as before.

The concept of GitLab CI is based on so-called runners which carry out the actual build scripts, GitLab CI is only responsible for orchestrating these runners and for the collection of results and artifacts. Runners can be Docker containers, VMs or bare metal machines, which ideally are not run on the same server as the orchestrator. As a result, the CI scripts do not have access to GitLab itself.

The runners check in with GitLab every few seconds via HTTPS and query if there is a job for them. GitLab cannot contact the runners by itself.
This makes it much easier to set up new runners, the only requirement is that the runner can connect to GitLab via HTTPS.

The runner component of GitLab is called gitlab-ci-multi-runner [^1] and is a statically compiled binary. In addition to Linux, it also supports builds on Windows, OSX and BSD.

The CI script for GitLab must be located in the root directory of the respective repo and have the file name .gitlab-ci.yml.

Enabling CI for a project

Starting with version 8.2, the CI component is integrated in GitLab and activated by default. It can, however, also only be activated and deactivated for individual projects.
The setting is called Builds and can be found under Features in the project settings:

GitLab does not delete any builds and artifacts that have already been implemented when the feature is deactivated, but just hides the Builds menu item.

These can still be viewed under Builds can, however, be deleted manually using the web interface. Starting with GitLab 8.9, it is possible to use the .gitlab-ci.yml to configure the length of time for with the results and artifacts are stored. [^2]



After CI has been activated in the web interface, a runner must be set up which executes the effective builds. In this example, gitlab-ci-multi-runner is set up on a Debian Jessie VM with the Docker executor. In the second part of this article, other runner configurations are discussed in more detail.

As a first step, the system should be updated:

# apt-get update
# apt-get upgrade

As Docker runners are used, Docker must be installed first:

# curl -sSL | sh

GitLab provides a script, which automatically configures the repository, the following command can be executed for this purpose:

# curl -L | sudo bash

The repo can also be activated in the traditional way if one wants to avoid an uncontrolled execution of scripts from the internet:

# echo "deb jessie main" >> /etc/apt/sources.list
# wget -qO - | apt-key add -
# apt-get update

Then, gitlab-ci-multi-runner can be installed via APT:

# apt-get install gitlab-ci-multi-runner

This sets up a systemd service, which should be activated and started by default:

# systemctl status gitlab-runner.service
● gitlab-runner.service - GitLab Runner
Loaded: loaded (/etc/systemd/system/gitlab-runner.service; enabled)
Active: active (running) since Mon 2016-09-19 18:33:32 CEST; 1 weeks 0 days ago
Main PID: 28102 (gitlab-ci-multi)
CGroup: /system.slice/gitlab-runner.service
└─28102 /usr/bin/gitlab-ci-multi-runner run --working-directory /home/gitlab-runner --config /etc/gitlab-runner/config.toml --service gitlab-runner --syslog...

The runner is now ready and can be registered and used in projects.

Registering runner

The newly installed runner must now be registered in GitLab. Each project has a unique runner token for this purpose, which can be viewed in the web interface under Project Settings > Runner:

This token can be used to activate the runner which was set up previously. To do so, enter the following command on the runner VM:

# gitlab-ci-multi-runner register 
--registration-token L4zpDbiAAA86sDnvYPkn 
--description "CI hello world" 
--executor "docker" 
--docker-image debian:jessie


  • --url GitLab CI URL
  • --registration-token Registration token
  • --description Description of the runner
  • --executor Executor, in this case Docker
  • --docker-image Docker-image, under which the runner is running. In this example, a Jessie container is used as a runner.

The runner should appear in the web interface after a few seconds:


After the runner has been set up and registered, the .gitlab-ci.yml must be created in the root directory of the project. In our example, only one file is created and a test is carried out to determine if it exists:

- test

  stage: test
  - touch foo
  - test foo

After committing and pushing, a running build should already appear under Builds:

The build should be completed after a few seconds:


In the second part, we will deal with real life application scenarios in more detail and introduce additional runner types.