26. Self-hosted GitLab Runner. About DevOps. Run CI jobs locally. Docker-in-Docker
Video version
(Leave your feedback on YouTube)
TL; DR
Never install GitLab Runner (or Jenkins, or anything else) on a production server. Use a separate deploy server or at least a stage server.
In the GitLab project: Build
=> Runners
=> New group runner
=> Enter a tag and copy the token.
I recommend using tags — it will help you understand which projects use which runners and will allow you to restrict resource usage for jobs.
Next, we deploy the runner in Docker:
docker run -d --name gitlab-runner --restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
/srv/gitlab-runner/config
contains the config.toml
configuration file.
docker exec -it gitlab-runner gitlab-runner register \
--non-interactive \
--name "local-dev" \
--url "https://gitlab.com/" \
--registration-token "secret" \
--executor "docker" \
--docker-image "docker:26.1.3" \
--docker-privileged \
--docker-volumes "/cache" \
--docker-volumes "/certs/client" \
--docker-shm-size 0
For Docker-in-Docker (DinD), the parameters docker-privileged
and docker-volumes "/certs/client"
are important.
The configuration file will be generated like this:
concurrent = 10
check_interval = 0
connection_max_age = "15m0s"
shutdown_timeout = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "local"
url = "https://gitlab.com/"
id = 41131741
token = "secret"
token_obtained_at = 2024-09-11T00:00:52Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "docker"
[runners.custom_build_dir]
[runners.cache]
MaxUploadedArchiveSize = 0
[runners.cache.s3]
[runners.cache.gcs]
[runners.cache.azure]
[runners.docker]
tls_verify = false
image = "docker:26.1.3"
privileged = true
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/cache", "/certs/client"]
shm_size = 0
network_mtu = 0
concurrent
is set to 1 by default, but I recommend increasing it to run multiple pipelines simultaneously.
DinD is important when running Docker containers as part of a job. It isolates the container within another container, prevents conflicts, and provides access to Docker’s file storage.