Today we will see how to run a rootless containerized gitlab-runner and their jobs with podman instead of docker. I will use a Debian 11 OS for this demo.

“rootless containerized” means your gitlab-runner container and their jobs will be executed in a user scope and not a root one with full power. It is better for your security. ;-)

At least gitlab-runner 15.3 and podman 4.2 versions are required.

podman setup

I already wrote a blog post about how to setup podman on Debian. Just read it :-)

Create a dedicated user

Create a dedicated user who will run and execute gitlab-runner and their jobs.

Ensure you added your user in /etc/subuid and /etc/subgid as explained in my blog article about how to setup podman on Debian.

It is a very important setting.

Additional user setup for podman

To make gitlab-runner works with podman in rootless mode, you need to enable the podman socket but you can’t with default Debian setup. It was a pain for me to get out of this.

Podman service is disabled. If you let this service disabled, your podman socket will be removed on a regulary basis and make your gitlab-runner container unstable. So enable and start the service:

# systemctl enable podman.service
# systemctl start podman.service

You need to enable linger on your account, this will activate dbus stuff needed for activating the podman socket:

# loginctl enable-linger your-username

Create /etc/profile.d/dbus.sh with this content to set needed environment variable (you can put them in ~/.bashrc too):

# cat << EOF | tee /etc/profile.d/dbus.sh > /dev/null
export XDG_RUNTIME_DIR=/run/user/$(id -u)
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus"
EOF

Note: I guess these environment variable exist when you are running Debian with a graphical interface but it is not the case in command-line only

Log yourself as your user and your will be able to enable the podman socket:

# su - your-user
$ systemctl enable --now --user podman.socket

That’s it!

gitlab-runner setup

Relevant docs:

So you just created your podman socket. We can now launch gitlab-runner as a container with podman.

We mount a local folder to store the config and the podman socket will be mounted as /var/run/docker.sock in the gitlab-runner container.

podman run -d \
  --name gitlab-runner \
  --restart always \
  -v ${HOME}/gitlab-runner-config:/etc/gitlab-runner \
  -v /run/user/$(id -u)/podman/podman.sock:/var/run/docker.sock \
  gitlab/gitlab-runner:latest

Note: You shoud use a specific tag and not the latest one for gitlab/gitlab-runner image.

additional setup

Grab your registration token from Settings > CI/CD > Runners from your project and register your runner:

podman exec -i gitlab-runner gitlab-runner register \
  --name your-runner-name \
  --url https://gitlab.com/ \
  --non-interactive \
  --executor docker \
  --docker-image alpine:latest \
  --registration-token ${REGISTRATION_TOKEN}

Let your gitlab-runner container starts on boot

The podman socket is not created as soon as the podman.socket service starts. There can be a delay for this and the gitlab-runner container won’t start at boot :-(

To fix this, you can create a /etc/systemd/system/podman-gitlab-runner.service systemd service with this content:

[Unit]
Description=Gitlab-runner with podman
Wants=podman.socket
After=podman.socket

[Service]
Type=oneshot
User=your-user
Group=your-group
ExecStartPre=/bin/bash -c "until test -S /run/user/$(id -u)/podman/podman.sock; do echo 'waiting for podman socket'; sleep 2; done"
ExecStart=/bin/bash -c "/usr/bin/podman restart gitlab-runner"
RemainAfterExit=true
StandardOutput=journal

[Install]
WantedBy=multi-user.target

This service will start after the podman.socket one, and will wait for the podman.sock availability before starting the gitlab-runner container. Of course, replace your-user and your-group with your user and group.

Reload systemd and enable this new service:

systemctl daemon-reload
systemctl enable podman-gitlab-runner.service

Conclusion

I hope you enjoyed this how-to. Feel free to share or contact me if you have questions.