Programster's Blog

Tutorials focusing on Linux, programming, and open-source

Deploy Gitlab Runner With Docker

Runners are isolated machines (preferably not installed on the same machine as Gitlab) that pick up and execute CI/CD jobs for your Gitlab server. A Runner can be specific to a certain project or serve any project in GitLab CI. A Runner that serves all projects is called a shared Runner. You don't have to have any runners at all if you are just using Gitlab for version control, but you will need at least one if you wish to implement CI/CD. You can deploy as many runners as you want and it is a good idea to scale horizontally across multiple servers.

Related Posts


Install Docker

Deploy a gitlab-runner container with docker.

docker run -d \
  --name gitlab-runner \
  --restart always \
  -v $HOME/gitlab-runner-volume/config:/etc/gitlab-runner \
  -v /var/run/docker.sock:/var/run/docker.sock \

This will result in any state being held in a directory at $HOME/gitlab-runner-volume. Feel free to change this path if you want it somewhere else, but I like it to be "in my face" so I don't forget it's there..


To update your runner, pull the latest image, remove the existing container and re-deploy.

docker pull gitlab/gitlab-runner:latest
docker stop gitlab-runner && docker rm gitlab-runner

docker run -d \
  --name gitlab-runner \
  --restart always \
  -v $HOME/gitlab-runner-volume/config:/etc/gitlab-runner \
  -v /var/run/docker.sock:/var/run/docker.sock \

Register The Runner

Go to the runners section of Gitlab and grab the url (4) and registration token (5)

Enter the container

After having grabbed the URL and token, you need to enter the container.

docker exec -it gitlab-runner /bin/bash

You now need to run one of the two commands below inside the container to register the runner. You can either explicitly specify your configuration options through arguments or run the command without the arguments and answer them in a series of interactive questions. I recommend going with explicit if you are unsure.

Option 1 - Explicit Registration

Run the command below after having substituted the variables or having set them. This uses the docker socket binding method so that the docker daemon is shared and your containers run directly on the host. You can use other methods if you like.


gitlab-runner register -n \
  --url $URL \
  --registration-token $REGISTRATION_TOKEN \
  --executor docker \
  --description "My Docker Runner" \
  --docker-image "docker:latest" \
  --docker-volumes /var/run/docker.sock:/var/run/docker.sock

Option 2 - Interactive Registration

Run the following command (inside the container):

sudo gitlab-runner register

You will be asked a series of questions. When asked for the url and token, enter the url and token that you grabbed earler from Gitlab.

When asked which type of executor, I went with docker and I suggest you do the same unless you specifically know that you want to use a different executor such as Kubernetes. You can read up more on runner executors. Whilst shell is the easiest, it results in an environment that gets polluted from past runs, unlike using docker whereby you start with a clean slate each time. I was unsure as to whether I wanted the docker executor or the docker-ssh executor, but it looks like the docker-ssh executor is being discontinued which made the choice easy.

Runner Registered

After having run the explicit command or using the interactive prompts, you will be shown the following error message:

Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

If you navigate back to the runners section of Gitlab, you will see your newly registered runner.


If you need to debug what it going wrong, use the command:

docker logs gitlab-runner

If you see this message:

ERROR: Failed to load config stat /etc/gitlab-runner/config.toml: no such file or directory  builds=0

That means that you probably haven't yet run the sudo gitlab-runner register command within your container yet. Please go back up to the register section.

At one point, I thought I needed to manually create the config.toml file using online examples, in order to register the runner. This will only end up in pain as you need to pass the token to the gitlab-runner register and if you try using that token within the config file you will end up with messages like this in the logs:

ERROR: Checking for jobs... forbidden               runner=9f09eda9
ERROR: Checking for jobs... forbidden               runner=9f09eda9
ERROR: Checking for jobs... forbidden               runner=9f09eda9
ERROR: Runner is not healthy and will be disabled!

Running Out Of Space

If you don't put something in place, your runners will probably eventually run out of space. Thus, I have it run a system prune every day.

sudo crontab -e
@daily /usr/bin/docker system prune -f

Even after that, my runner still ran out of space, so I added the following:

@daily /usr/bin/docker image prune --all --force


Last updated: 5th April 2024
First published: 16th August 2018