GitLab Runner Registration and Docker Executor Setup - 夜莺博客

GitLab Runner Registration and Docker Executor Setup

A GitLab Runner is the process that actually executes your CI jobs, and almost every "pipeline stuck in pending" incident traces back to runner registration or executor configuration rather than to the pipeline YAML. Since GitLab moved to runner authentication tokens, the registration flow changed, and the old --registration-token approach is deprecated. This guide covers installing a runner, registering it with an authentication token, configuring the Docker executor in config.toml, and diagnosing a runner that is registered but never picks up work.

Runner Concepts You Need First

  • Runner type — instance, group, or project. Scope determines which projects the runner can serve, and a project runner will never run an instance-wide job.
  • Executor — how jobs run. docker gives each job a clean container; shell runs directly on the host; kubernetes schedules pods.
  • Tags — the mechanism that matches jobs to runners. A job with no tag only runs on a runner configured to accept untagged jobs.
  • Authentication token — the replacement for the deprecated registration token, generated per runner in the GitLab UI.

Step 1 - Install the Runner

Install the package for your platform and confirm the binary and version:

curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt install -y gitlab-runner
gitlab-runner --version
sudo systemctl status gitlab-runner

On rpm distributions use the matching rpm script. The version should be close to your GitLab server version; a runner several major versions behind will register but fail on newer features.

Step 2 - Register with an Authentication Token

Create the runner in the GitLab UI first (Settings > CI/CD > Runners or the admin area), copy the authentication token, then register non-interactively:

sudo gitlab-runner register \
  --non-interactive \
  --url "https://gitlab.example.com/" \
  --token "$RUNNER_AUTH_TOKEN" \
  --executor "docker" \
  --docker-image "alpine:latest" \
  --docker-pull-policy "if-not-present" \
  --description "docker-runner-01" \
  --tag-list "docker,linux,prod" \
  --run-untagged="false" \
  --locked="false"

If the runner itself runs inside a container, register it through a short-lived container sharing the config volume so that config.toml is written to the right place:

docker run --rm -it -v /srv/gitlab-runner/config:/etc/gitlab-runner \
  gitlab/gitlab-runner register \
  --non-interactive --url "https://gitlab.example.com/" \
  --token "$RUNNER_AUTH_TOKEN" --executor "docker" --docker-image alpine:latest

Step 3 - Configure the Docker Executor

Registration writes a skeleton config.toml, typically at /etc/gitlab-runner/config.toml. This is where concurrency, resource limits and pull policies live:

concurrent = 8
check_interval = 3

[[runners]]
  name = "docker-runner-01"
  url = "https://gitlab.example.com/"
  executor = "docker"
  [runners.docker]
    image = "alpine:latest"
    privileged = false
    pull_policy = ["if-not-present"]
    allowed_pull_policies = ["always", "if-not-present"]
    memory = "4g"
    cpus = "2"
    helper_image = ""
    volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]
    network_mode = "bridge"
  [runners.cache]
    type = "local"
    path = "/cache"

Concurrency, privileged mode and the Docker socket

Notes on the settings that matter. concurrent at the top level caps how many jobs run simultaneously across all runners, and each runner also has its own limit under [[runners]]. privileged = false is the secure default; enable it only for jobs that genuinely need to run Docker inside Docker, and prefer a Kaniko or BuildKit builder instead. Mounting /var/run/docker.sock gives the job root-equivalent access to the host daemon — convenient for image builds, and a serious escalation risk if jobs come from untrusted merge requests. allowed_pull_policies constrains what a job's own pull_policy may request.

After any edit, restart and verify the config is valid:

gitlab-runner verify
sudo systemctl restart gitlab-runner
gitlab-runner list
gitlab-runner verify --delete

Step 4 - Confirm the Runner Picks Up Jobs

sudo systemctl status gitlab-runner
sudo journalctl -u gitlab-runner -f
gitlab-runner list
gitlab-runner verify

In the GitLab UI the runner should show a green circle with a "last contact" timestamp within the check interval. If it shows as never contacted, the problem is connectivity or token, not the executor.

Troubleshooting a Stuck Pipeline

The four causes of a stuck pipeline

Work through the four usual causes in order:

  1. Tag mismatch. The job specifies tags the runner does not declare, or the job expects a runner that accepts untagged jobs and none is configured that way. Check the job's tags: against gitlab-runner list.
  2. Concurrency exhausted. Every slot is busy running long jobs. The pipeline log will say the job is waiting for a runner, and the runner's own log shows the current job count.
  3. Runner paused or offline. A runner that was paused in the UI stays registered but takes no work — this is a common leftover after maintenance.
  4. Executor failure. The runner picks the job up and then fails immediately. The job log shows the error; typical causes are a missing default image, an unpullable image, or insufficient disk space for the build directory.
df -h /var/lib/gitlab-runner /var/lib/docker
docker images | head
docker ps -a | head

Operational Notes

  • Register runners against the smallest scope that works — project runners for dedicated workloads, instance runners only when you intend to serve all projects.
  • Keep privileged off and avoid mounting the Docker socket unless the pipeline truly requires image builds.
  • Set a default image both in config.toml and in the job, so a missing image never blocks a pipeline.
  • Prune Docker images and old build directories on a schedule; the executor host filling up is the most common mid-life failure.
  • Verify after every config change — gitlab-runner verify catches typos that would otherwise only show up at job time.

Related reading: our Docker Compose depends_on and healthcheck startup order guide, the Docker overlay2 disk full cleanup guide, and the ArgoCD app-of-apps sync waves article.

原文链接:https://docs.gitlab.com/runner/register/