„Die Anweisung ist hochgeladen, aber warum passiert nichts?“
Beim letzten Mal hatte ich voller Tatendrang die Datei .gitlab-ci.yml geschrieben und mit push hochgeladen. „Jetzt wird das Deployment doch automatisch laufen, oder?“, dachte ich voller Erwartung und klickte in GitLab auf das Menü ‚CI/CD > Pipelines‘.
Doch statt eines grünen Erfolgssymbols sah ich nur einen endlos rotierenden Ladebalken und die Statusmeldung ‚Pending‘. Als ich auf die Meldung klickte, erschien folgende Warnung:
This job is stuck because the project doesn't have any runners online assigned to it.
Übersetzt heißt das: „Es ist ein Auftrag eingegangen, aber der zuständige Mitarbeiter (Runner) ist nicht zur Arbeit erschienen.“ Tatsächlich – ich hatte dem Werksleiter (GitLab Server) zwar die Arbeitsanweisung übergeben, aber niemanden eingestellt, der die Arbeit in der Fabrik tatsächlich erledigt (Runner).

GitLab Runner: Die Hände und Füße der Pipeline
GitLab besteht im Wesentlichen aus zwei Komponenten.
- GitLab Server (Hauptsitz/Werksleiter): Speichert den Code, verwaltet den Status der Pipeline und erteilt Anweisungen.
- GitLab Runner (Zweigstelle/Mitarbeiter vor Ort): Wird auf dem eigentlichen Server installiert, nimmt die Anweisungen des Hauptsitzes entgegen, holt den Code, baut ihn und führt die Deployment-Befehle aus.
„Kann GitLab nicht einfach selbst auf meinen Server zugreifen und das Deployment ausführen?“ Wenn man genauer darüber nachdenkt, wäre das eine hochgefährliche Sache. Stellen Sie sich vor, eine Webseite im Internet (GitLab) könnte per Knopfdruck auf den Computer in Ihrem Zimmer (den Server) zugreifen und dort beliebige Befehle ausführen. Das wäre nichts anderes als ‚Hacking‘. Würde jemand Ihren GitLab-Account knacken, könnte er Ihren Server in eine Bitcoin-Mining-Maschine verwandeln.
Deshalb greift GitLab nicht direkt auf Ihren Server zu. Stattdessen wird ein ‚verifizierter Stellvertreter (Runner)‘ eingesetzt, der ausschließlich innerhalb Ihres Servers arbeitet und alle Aufträge nur über diesen Stellvertreter ausführen lässt. Der etwas komplizierte Installations- und Registrierungsprozess, den wir gleich durchlaufen, ist genau diese ‚Sicherheitsprozedur‘ zur Authentifizierung des Stellvertreters.
Schritt 1: Stellenausschreibung prüfen (Token erhalten)
Bevor wir den Runner installieren, müssen wir zunächst beim Hauptsitz (GitLab) eine ‚Stellenausschreibung‘ veröffentlichen, die besagt: „Unser Projekt benötigt einen Mitarbeiter“, und einen ‚Ausweis (Token)‘ erhalten.
In den neuesten GitLab-Versionen ist die Methode zum Anzeigen des Tokens aus Sicherheitsgründen etwas versteckt.
- Das GitLab-Projekt öffnen
- Im linken Menü: Settings > CI/CD
- Im Abschnitt Runners auf
Expandklicken - Oben rechts im Abschnitt Project runners auf die Schaltfläche mit den drei Punkten (⋮) klicken
Beim Klick auf diese Schaltfläche öffnet sich ein Popup-Menü mit den gesuchten Informationen. Notieren und kopieren Sie die URL und das Registration token.
(Hinweis: Es kann eine beunruhigende Warnung erscheinen: ‚Support for registration tokens is deprecated‘. Das bedeutet, dass diese Methode bald entfernt wird, aber aus Kompatibilitätsgründen vorerst noch unterstützt wird. Lassen Sie sich also nicht verunsichern und kopieren Sie einfach den Token.)
[Tipp] Mehrere Projekte? (Group Runner) Wenn Sie wie ich mehrere Projekte – Frontend, Backend usw. – in einer Gruppe verwalten, ist es ineffizient, für jedes Projekt einzeln einen Runner zu registrieren. In diesem Fall registrieren Sie den Runner nicht in den Projekteinstellungen, sondern unter Group Settings > CI/CD. Ein so erstellter ‚Group Runner‘ kann alle Aufträge sämtlicher Projekte dieser Gruppe alleine bearbeiten. (Da ich viele Projekte habe, habe ich diese Variante gewählt.)

Schritt 2: Mitarbeiter einstellen (Runner installieren)
Jetzt installieren wir den Runner tatsächlich auf einem Linux-Server (oder dem eigenen PC). Die sauberste Methode ist – wie nicht anders zu erwarten – unser geliebtes ‚Docker‘.
# 1. GitLab-Runner-Container starten
docker run -d --name gitlab-runner --restart always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v gitlab-runner-config:/etc/gitlab-runner \
gitlab/gitlab-runner:latest
-v /var/run/docker.sock:/var/run/docker.sock: Das ist wichtig. Da der Runner seinerseits weitere Docker-Container (für den Build) starten muss, wird ihm der Docker-Socket des Hosts zur Verfügung gestellt. (Docker-in-Docker-Ansatz)
Schritt 3: Arbeitsvertrag aufsetzen (Runner registrieren)
Mit der Installation des Runners ist es noch nicht getan. Der Runner muss sich beim GitLab-Server registrieren mit dem Hinweis: „Ich bin Mitarbeiter von Projekt A.“
Steigen Sie in den soeben gestarteten Runner-Container ein und führen Sie den Registrierungsbefehl aus.
# Registrierungsbefehl im Runner-Container ausfuehren
docker exec -it gitlab-runner gitlab-runner register
Im Terminal beginnt nun eine Reihe von Fragen wie bei einem Quiz. Geben Sie einfach die Informationen ein, die Sie in Schritt 1 erhalten haben.
- Enter the GitLab instance URL:
https://gitlab.com/(oder die Adresse Ihres privaten GitLab-Servers)
- Enter the registration token:
- (Den zuvor kopierten Token einfügen)
- Enter a description for the runner:
my-runner-01(beliebig, Hauptsache ein leicht erkennbarer Name)
- Enter tags for the runner:
- (Kann mit Enter übersprungen werden. Wird verwendet, wenn der Runner nur Jobs mit bestimmten Tags ausführen soll.)
- Enter an executor:
docker(Da wir auf Docker bauen wollen, geben wir docker ein.)
- Enter the default Docker image:
docker:latest(das standardmäßig verwendete Image)
„Runner registered successfully.“ Wenn diese Meldung erscheint, ist die Einstellung abgeschlossen! Aktualisieren Sie nun das GitLab-Fenster, und Sie sehen den Runner mit grüner Anzeige, der ruft: „Bereit (Online)“.

Schritt 4: Pipeline starten!
In dem Moment, in dem der Runner registriert wird, beginnt die zuvor stehengebliebene (Pending) Pipeline automatisch zu laufen. Running… und kurz darauf: Passed!
Ohne dass ich etwas tun musste, hat die Maschine selbstständig die Tests durchgeführt, das Build erstellt, das Image gebaut und in die Registry hochgeladen. Beim Blick ins Terminal zeigte sich, dass der gesamte Prozess viel schneller und präziser abgelaufen war, als wenn ich ihn manuell durchgeführt hätte.
„Wow… das funktioniert wirklich!“
Was zuvor 10 Minuten manuelles Deployment kostete, erledigt sich jetzt mit einem einzigen git push. Ich kann jetzt das Deployment anstoßen und in Ruhe einen Kaffee trinken gehen.
Praxis-Tipp: Docker-Berechtigungsproblem (Permission Denied)
Beim erstmaligen Einrichten des Runners stößt man mit 99 % Wahrscheinlichkeit auf folgenden Fehler: dial unix /var/run/docker.sock: connect: permission denied
Das Problem entsteht, weil der Runner Docker-Befehle ausführen möchte, aber keine Berechtigung dafür hat. In diesem Fall öffnen Sie die Konfigurationsdatei des gitlab-runner (config.toml) und aktivieren die Option privileged = true.
# /etc/gitlab-runner/config.toml (Runner-Konfigurationsdatei)
[[runners]]
name = "my-runner-01"
executor = "docker"
[runners.docker]
privileged = true # Diesen Wert auf true setzen, damit Docker-in-Docker funktioniert. # …
Fazit: Jetzt kann ich Feierabend machen
Endlich habe ich meinen eigenen ‚Deployment-Roboter‘. Jetzt kann ich mich ganz auf das Schreiben von Code konzentrieren. Die langweiligen, repetitiven Verifizierungs- und Deployment-Aufgaben übernimmt mein treuer Roboter (Runner) für mich.
Aber 2 % fehlen noch. Aktuell läuft die Pipeline jedes Mal, wenn etwas in den master-Branch gepusht wird. „Was ist, wenn ich zwar automatisch auf den Entwicklungsserver (dev) deployen möchte, den Produktivserver (prod) aber nur dann, wenn ich auf ‚Genehmigen‘ klicke?“
Beim nächsten Mal werfen wir einen Blick auf die intelligentere Steuerung der Pipeline – auf ‚Branch-spezifische Deployment-Strategien‘ und ‚manuelle Genehmigungsverfahren (Manual)‘.


