How to Configure GitLab Runner with Docker Executor on Ubuntu 24.04 EC2
In this tutorial, we will configure a self-hosted GitLab Runner with Docker Executor on an AWS EC2 Ubuntu 24.04 instance.
With the Docker executor, each GitLab CI/CD job runs inside an isolated Docker container. This allows the same runner to execute pipelines using different environments such as Maven, Python, Node.js, or Ubuntu without installing all of those tools directly on the EC2 instance.
Architecture
Developer → GitLab Repository → GitLab CI/CD Pipeline → Self-Hosted GitLab Runner → Docker Executor → Docker Container → Execute CI/CD Job
Prerequisites
Before starting, make sure you have:
- AWS account
- Ubuntu 24.04 EC2 instance
- GitLab account
- GitLab project
- SSH access to the EC2 instance
sudoprivileges
For a learning environment, an EC2 instance with at least 2 GB RAM is recommended.
Step 1 — Connect to Ubuntu EC2
SSH into the EC2 instance:
ssh -i your-key.pem ubuntu@<EC2-PUBLIC-IP>
Verify the operating system:
cat /etc/os-release
You should see Ubuntu 24.04 LTS.
Step 2 — Update Ubuntu
Update the package information:
sudo apt update
Step 3 — Install Docker
Install Docker:
sudo apt install docker.io -y
Start Docker:
sudo systemctl start docker
Enable Docker during system startup:
sudo systemctl enable docker
Verify:
sudo systemctl status docker
Check the Docker version:
docker --version
Step 4 — Test Docker
Run:
sudo docker run hello-world
If Docker is configured correctly, Docker downloads the test image and starts a container.
Step 5 — Install GitLab Runner
Add the official GitLab Runner repository:
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
Install GitLab Runner:
sudo apt install gitlab-runner -y
Verify:
gitlab-runner --version
Check the service:
sudo systemctl status gitlab-runner
Step 6 — Allow GitLab Runner to Access Docker
The GitLab Runner service normally runs using the
gitlab-runner Linux account.
Add that account to the docker group:
sudo usermod -aG docker gitlab-runner
Restart Docker:
sudo systemctl restart docker
Restart GitLab Runner:
sudo systemctl restart gitlab-runner
Now verify that the GitLab Runner account can communicate with Docker:
sudo -u gitlab-runner docker info
If this command works successfully, the runner should be able to use the Docker executor.
Step 7 — Create a Runner in GitLab
Open your GitLab project.
Navigate to:
Settings → CI/CD → Runners
Create a new project runner.
You can configure a runner tag such as:
docker
GitLab will provide a runner authentication token.
Keep this token secure.
Step 8 — Register the GitLab Runner
On your Ubuntu EC2 instance, run:
sudo gitlab-runner register
Enter the GitLab URL:
https://gitlab.com/
Enter the runner authentication token provided by GitLab.
When prompted for the name for the runner, enter:
docker-runner
When prompted for the executor, enter:
docker
When prompted for the default Docker image, enter:
ubuntu:24.04
The runner should now be registered.
Step 9 — Verify the Runner
List configured runners:
sudo gitlab-runner list
Verify connectivity with GitLab:
sudo gitlab-runner verify
Check the service:
sudo systemctl status gitlab-runner
Go back to:
GitLab → Project → Settings → CI/CD → Runners
The runner should appear online.
Step 10 — Review GitLab Runner Configuration
The system-mode GitLab Runner configuration is normally stored here:
sudo cat /etc/gitlab-runner/config.toml
You should see configuration similar to:
[[runners]]
name = "ubuntu-docker-runner"
executor = "docker"
[runners.docker]
image = "ubuntu:24.04"
The exact configuration generated by your GitLab Runner version can contain additional settings.
Step 11 — Create a Simple GitLab CI/CD Pipeline
Create a file in the root of your GitLab repository:
.gitlab-ci.yml
Add:
stages:
- test
test-docker-runner:
stage: test
tags:
- docker
image: ubuntu:24.04
script:
- echo "GitLab Docker Runner is working!"
- hostname
- whoami
- cat /etc/os-release
Commit and push the file.
GitLab should automatically start a pipeline.
Step 12 — Verify the Pipeline
The pipeline flow is:
↓
GitLab CI/CD Pipeline
↓
Self-Hosted GitLab Runner
↓
Docker Executor
↓
Pull
ubuntu:24.04 Docker Image↓
Create Temporary Container
↓
Execute CI/CD Commands
↓
Job Completes
The job container is temporary. GitLab Runner creates the container for the job and removes it after the job finishes.
Understanding Docker Executor
One of the major advantages of Docker executor is that the EC2 instance does not need every development tool installed directly on the host.
For example, a Maven job can use:
build:
image: maven:3.9-eclipse-temurin-17
script:
- mvn clean package
Another job on the same runner could use:
test:
image: ubuntu:24.04
script:
- echo "Running Ubuntu container"
Therefore, a single Docker executor can support many different CI/CD workloads.
Common Error 1 — Docker Socket Permission Denied
You may encounter:
permission denied while trying to connect to the Docker daemon socket
unix:///var/run/docker.sock
Check Docker access:
sudo -u gitlab-runner docker info
If access is denied, make sure the runner account belongs to the Docker group:
sudo usermod -aG docker gitlab-runner
sudo systemctl restart docker
sudo systemctl restart gitlab-runner
Test again:
sudo -u gitlab-runner docker info
Common Error 2 — ubuntu-latest Image Cannot Be Pulled
You may see:
Failed to pull image "ubuntu-latest"
pull access denied for ubuntu-latest,
repository does not exist
Do not use:
ubuntu-latest
That naming is commonly seen with GitHub Actions runners:
runs-on: ubuntu-latest
For a Docker image, specify the repository and tag:
ubuntu:24.04
For example:
image: ubuntu:24.04
If the default image is configured incorrectly, edit:
sudo nano /etc/gitlab-runner/config.toml
Change:
image = "ubuntu-latest"
to:
image = "ubuntu:24.04"
Then restart:
sudo systemctl restart gitlab-runner
Common Error 3 — Job Stuck in Pending
If you see:
This job is in pending state and is waiting to be picked by a runner
Check whether the runner is online:
sudo gitlab-runner verify
Check the service:
sudo systemctl status gitlab-runner
Also verify that the tags in .gitlab-ci.yml match the tags
assigned to the GitLab Runner.
For example:
tags:
- docker
requires a runner capable of accepting jobs with the docker tag.
Common Error 4 — Runner Started in User Mode
If you run:
gitlab-runner run
without sudo, you may see:
WARNING: Running in user-mode.
Starting multi-runner from /home/ubuntu/.gitlab-runner/config.toml
For a server-based self-hosted runner, it is generally better to install and operate GitLab Runner as a system service.
Register using:
sudo gitlab-runner register
The system configuration is then normally maintained under:
/etc/gitlab-runner/config.toml
Manage the runner using:
sudo systemctl start gitlab-runner
sudo systemctl stop gitlab-runner
sudo systemctl restart gitlab-runner
sudo systemctl status gitlab-runner
Useful Troubleshooting Commands
Check GitLab Runner:
sudo gitlab-runner list
Verify registered runners:
sudo gitlab-runner verify
Check Runner service:
sudo systemctl status gitlab-runner
Check Runner logs:
sudo journalctl -u gitlab-runner -f
Check Docker:
sudo systemctl status docker
Check Docker access for the runner:
sudo -u gitlab-runner docker info
List running containers:
docker ps
List all containers:
docker ps -a
Conclusion
We successfully configured a self-hosted GitLab Runner using Docker Executor on an Ubuntu 24.04 AWS EC2 instance.
The architecture is:
Developer → GitLab → GitLab CI/CD → Self-Hosted Runner → Docker Executor → Job Container
Using Docker executor provides isolation and flexibility because different CI/CD jobs can use different container images without requiring every build tool to be installed directly on the runner EC2 instance.
You can now extend this setup to build real CI/CD pipelines using:
- Maven and Java
- SonarQube
- Trivy
- Docker
- Terraform
- Python
- Node.js
- Other DevSecOps tools


