GitLab FI
GitLab Continuous Integration
GitLab Continuous Integration (CI) is used to automate some development tasks in a repository, most commonly for automated unit testing. You can
configure your own physical or virtual machine to use GitLab CI (see
Stratus.FI virtualization). In addition, you can also use the faculty machine
gitlab-ci.fi.muni.cz.
Summary
The faculty
gitlab-ci.fi uses the official
GitLab Runner with container isolation in
Docker. When a new task is started (e.g., following
git push into the repository), the GitLab Runner asks Docker to create a new container from the image that is declared in the repository in the file
.gitlab-ci.yml.
The container clones the repository and runs the tasks described in that file. When finished, the container is dropped and the result is returned to GitLab, which displays it in the
CI/CD section.
Configuring the project for
gitlab-ci.fi.muni.cz
First, read the
introductory information for using GitLab CI/CD. Next, you will need
the documentation for
.gitlab-ci.yml.
Selecting an image
The image to be used is declared in the
.gitlab-ci.yml configuration as the value of the
image key. The format is either
REPOSITORY:TAG or
REPOSITORY (the default tag is then
latest). If no image is specified,
alpine:latest is used.
image: maven:latestSelecting the version
Docker image tags are not static, i.e.,
X:3.0 is just a symbolic name for a version of an image, and it may happen at any time that the repository maintainer changes the image to which the tag points. The versioning of images and the meaning of the versions themselves depends on the maintainers of the individual Docker repositories, but
in general it is advisable to follow the principles of semantic versioning.
If possible, prefer images in the most generic major version (e.g., prefer
X:3 instead of
X:3.5.0) so that your project has an image with security patches and bug fixes for the software used.
However,
we do not recommend using
latest for important projects. This symbolic marker
usually points to the latest stable version of the image, but it may move to a newer version that is not backwards compatible without warning.
Marker settings
To prevent the machine from being overwhelmed by tasks from repositories that have their own CIs set,
gitlab-ci.fi only accepts tasks from projects that are tagged with the
shared-fi tag , which can be set as follows:
- in Settings → General → Permissions, enable the Pipelines option if it is not already enabled
-
in the
.gitlab-ci.ymlsettings, add theshared-fitag to each target, e.g.:build: tags: - shared-fi
Artifact settings
For projects that create artifacts, we recommend setting CIs so that GitLab automatically cleans them up when newer ones are created.
First, ensure that GitLab preserves the most recent artifact in the project:
Project →
Settings →
CI/CD →
Artifacts→ check
Keep artifacts from most recent successful jobs
Then add a setting to
.gitlab-ci.yml that sets the artifact lifetime to a very small value (less than 2 hours, e.g. 10 minutes). Set this for
each job
JOB.
With the setting above, the last artifact will be preserved after the lifetime expires.
‹JOB›:
artifacts:
…
expire_in: 10 minutesExamples
In the FI faculty GitLab you can take a look at the project
unix/ci-examples, where you can find examples of CI configuration for simple projects.
Container Registry
The Container Registry service gives users the ability to save images to a Docker project that can then be used in CI or other projects.
The images do not need to be related to the content of the project in any way. However, you will likely have
Dockerfile and other dependencies for the image, so we recommend creating a repository for these files that also keeps the image version up to date.
The Container Registry can be accessed from the
gitlab.fi.muni.czmachine and the
5050 port.
Service Settings
Switching on the service
In the project that is to maintain the build images, turn on
Settings → General → Visibility, project features, permissions→ Container Registry.
The service does not need to be turned on for projects that are only going to use the image in CI.Limit on the number of tags
Images in the Container Registry usually take up a lot of space. Frequently changing tags can quickly exhaust disk space, so turn on automatic cleanup for the project:
In Settings → Packages & Registries , turn on Clean up image tags. We also recommend changing the Keep the most recent: setting to 5 tags per image name.Access to the image
Access to images is generally governed by the access rights of the parent project:
- Private - Project members only
- Internal - Only people logged into GitLab FI
- Public - Unrestricted
Creating an image
Manually
The easiest way to build an image is to use a Docker or Podman instance on your own machine. This option is useful for situations where the image doesn't change often and setting up an automatic build using CI would be impractical.
The name of the image to be placed in the GitLab Container Registry must begin with the domain and port in the format
gitlab.fi.muni.cz:5050, and continue with the path to the project. So, for example, for the
https://gitlab.fi.muni.cz/NAMESPACE/PROJECT.git project, images with names like
-
gitlab.fi.muni.cz:5050/NAMESPACE/PROJECT:TAG -
gitlab.fi.muni.cz:5050/NAMESPACE/PROJECT/IMAGE:TAG -
gitlab.fi.muni.cz:5050/NAMESPACE/PROJECT/NAME/IMAGE:TAG
In the directory with
Dockerfile or
Containerfile
build the image (use one of the formats above as the image name):
$ docker build -t gitlab.fi.muni.cz:5050/‹LOGIN›/‹PROJECT›:‹TAG› .
If you are satisfied with the image, you can upload it to the Container Registry.
The first thing to do is to log in to your client, using a password (only possible if you don't have 2FA enabled) or a
GitLab access token, which must have at least the rights
read_registry and
write_registry.
$ docker login --username ‹LOGIN› gitlab.fi.muni.cz:5050
Use your faculty login instead of
‹LOGIN›. When prompted for a password, use the password or token.
Then upload the image to the Container Registry:
$ docker push gitlab.fi.muni.cz:5050/‹NAMESPACE›/‹PROJECT›:‹TAG›
Automatically building an image in the faculty GitLab CI
Faculty GitLab CI has been providing the ability to build images since 11/2025 using Rootless Docker-in-Docker.
In a project with an image source (typically
Dockerfile or
Containerfile), add
.gitlab-ci.yml. Tasks that want to use Docker to build an image (i.e., call
docker build) must meet the following conditions:
- They must use the image
docker:cliordocker:‹version›-cli. - They must run
docker:dind-rootlessordocker:‹version›-dind-rootless. - They must have the
DOCKER_HOST=unix:///runner/services/docker/docker.sockenvironment variable set. - It must have the
shared-fitag . If you come across a project with theshared-fi-dindtag, then it is a tag from the testing phase; you don't need to fix it, but don't use it in new projects.
The same conditions apply for uploading as for
manual builds, especially for the image name. GitLab CI will insert its own pronouns into the environment for authentication to the Container Registry (
CI_REGISTRY,
CI_REGISTRY_USER,
CI_REGISTRY_PASSWORD). So just execute this command before
docker push:
echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
.gitlab-ci.yml or anywhere else in the project!
For a sample setup, see the
ci-dind-example project
in the faculty GitLab.
Automatic image building in custom CI
Prior to Rootless Docker-in-Docker in the faculty GitLab CI, this was the only way to automate. It may still be relevant for custom experimentation and resource- or time-intensive builds; in other circumstances, we recommend using a faculty instance.
Virtual machine or computer?
We strongly recommend using a virtual machine in Stratus.FI for this task. It should be sufficient to use a pre-installed virtual machine.
Using your own machine is also possible. Note, however, that there is a risk of escalating permissions or taking control of the machine in case of a configuration error. The same risk applies to the virtual machine, but the extent of the problem is smaller in this case.Docker and Docker
Configure CI Runner to build Docker images according to the official instructions. We recommend the Docker-in-Docker option.Registration
Register the Runner only for the project in which the images are to be built, see Project Runners.Project security
Ensure that only trusted users in the project (Owner, Maintainer) can run a CI job. In particular, prevent untrusted users from creating a Merge Request with custom code for which the job would run.
See Protected Branches and Rules for.gitlab-ci.yml.Location of .gitlab-ci.yml
A potential attacker can modify.gitlab-ci.ymlat will and bypass the settings above. This is a serious problem especially for public and internal projects.
This problem can be solved by setting the project to look for.gitlab-ci.ymlin another private repository where only trusted users can modify it. The local file will then be ignored. See Custom CI/CD configuration file → Custom CI/CD configuration file examples.
Note that settingCODEOWNERSis not enough, it will only prevent an unwanted Merge if the protected file has changed, but the CI tasks will still run.
If you rarely build an image, the safest option is to build the image locally.
Common problems and solutions
Stuck tasks
If you encounter a
Job is stuck error after configuring your project, you probably did not include the
shared-fi tag in the job configuration. Check your settings as
described above.
Cannot use Docker commands in a job
If you encounter an error like
dial tcp: lookup docker on 147.251.48.14:53: no such host, you are probably trying to use the Faculty CI Runner in privileged mode. This is only allowed under the conditions
for automatic builds in Faculty GitLab CI. If you still think this is an error, contact
administrator.