Zur Übersicht

GitLab CI/CD: Pipeline erstellen und automatisiert deployen

GitLab CI/CD verständlich erklärt: .gitlab-ci.yml, Stages, Jobs, Runner, Caching, Artefakte und Deployment. Schritt für Schritt zur eigenen Pipeline.

Manuelles Testen und Deployen ist fehleranfällig, langsam und nervig. GitLab CI/CD automatisiert den gesamten Weg vom Commit bis zur Produktion: Bei jedem Push laufen automatisch Tests, Builds und – wenn alles grün ist – das Deployment. Das Schöne daran: Die gesamte Konfiguration steckt in einer einzigen Datei im Repository, versioniert und nachvollziehbar wie der Code selbst. Dieser Artikel führt dich von den Grundbegriffen bis zur ersten lauffähigen Pipeline.

Die Grundbegriffe von GitLab CI/CD

Bevor wir Konfiguration schreiben, klären wir die zentralen Begriffe:

  • Pipeline: Der gesamte automatisierte Ablauf, der bei einem auslösenden Ereignis (z. B. Push, Merge Request) startet.
  • Stage: Eine Phase der Pipeline, etwa build, test, deploy. Stages laufen nacheinander.
  • Job: Eine konkrete Aufgabe innerhalb einer Stage, z. B. "Unit-Tests ausführen". Jobs derselben Stage laufen parallel.
  • Runner: Der Agent, der die Jobs tatsächlich ausführt – auf einem Server, in einem Container oder in der Cloud.

Die komplette Konfiguration liegt in der Datei .gitlab-ci.yml im Wurzelverzeichnis deines Repositorys. GitLab erkennt sie automatisch und startet bei jedem Push die definierte Pipeline.

Die erste .gitlab-ci.yml

Eine minimale Pipeline definiert Stages und ordnet Jobs zu. Konzeptionell sieht das so aus: Du legst oben die Reihenfolge der Stages fest und definierst dann pro Job, in welche Stage er gehört und welche Befehle (das script) er ausführt.

Ein typisches Beispiel für eine Node-Anwendung umfasst drei Stages:

  • build: Ein Job build-job, der npm ci und npm run build ausführt und das Build-Ergebnis als Artefakt sichert.
  • test: Ein Job test-job, der die Testsuite mit npm test durchlaufen lässt.
  • deploy: Ein Job deploy-job, der nur auf dem Hauptbranch läuft und die Anwendung auf den Zielserver bringt.

Jeder Job gibt mit dem Schlüssel image an, in welchem Docker-Image er ausgeführt wird (etwa node:20-alpine). Das macht Builds reproduzierbar, weil jeder Job in einer sauberen, definierten Umgebung startet.

Runner: Wer führt die Jobs aus?

Ohne Runner passiert nichts. Auf gitlab.com stehen geteilte Runner (Shared Runners) bereit, sodass du sofort loslegen kannst – allerdings im Rahmen eines Minutenkontingents. Bei einer selbst gehosteten GitLab-Instanz oder für mehr Kontrolle registrierst du eigene Runner.

Am verbreitetsten ist der Docker-Executor: Jeder Job läuft in einem frischen Container des angegebenen Images. Das garantiert Isolation und Sauberkeit. Alternativen sind der Shell-Executor (Jobs laufen direkt auf dem Runner-Host) und der Kubernetes-Executor (Jobs als Pods im Cluster). Für die meisten Teams ist der Docker-Executor die richtige Wahl.

Caching und Artefakte richtig nutzen

Ein häufiger Anfängerfehler: In jedem Job werden Abhängigkeiten neu heruntergeladen, was die Pipeline unnötig verlangsamt. Hier helfen zwei Konzepte, die man nicht verwechseln sollte:

  • Cache: Beschleunigt Pipelines, indem wiederverwendbare Daten (z. B. node_modules oder das .npm-Verzeichnis) zwischen Pipeline-Läufen erhalten bleiben. Der Cache ist eine Performance-Optimierung und darf verloren gehen.
  • Artefakt: Ein Ergebnis eines Jobs, das an nachfolgende Jobs weitergegeben oder zum Download bereitgestellt wird – etwa das fertige Build-Verzeichnis oder ein Test-Report. Artefakte sind verlässlich und werden für eine konfigurierbare Zeit aufbewahrt.

Faustregel: Den Cache nutzt du für Abhängigkeiten, die du nicht im Repo hast, aber regenerieren könntest. Artefakte nutzt du, um Build-Ergebnisse von einer Stage zur nächsten zu reichen.

Pipeline gezielt steuern mit Rules

Selten soll jeder Job bei jedem Anlass laufen. Das Deployment in die Produktion etwa sollte nur vom Hauptbranch erfolgen, nicht von jedem Feature-Branch. Dafür gibt es das Schlüsselwort rules (das ältere only/except gilt als veraltet). Mit rules definierst du Bedingungen, etwa:

  • Den Deploy-Job nur ausführen, wenn der Branch main ist.
  • Bestimmte Jobs nur bei Merge Requests laufen lassen.
  • Ein Deployment in Produktion als manual markieren, sodass es erst nach einem bewussten Klick im GitLab-UI startet (ein manuelles Freigabe-Gate).

Gerade das manuelle Gate für Produktions-Deployments ist eine bewährte Sicherheitsmaßnahme: Tests und Staging-Deployment laufen automatisch, aber der finale Schritt in die Produktion bleibt in menschlicher Hand.

Secrets und Variablen sicher verwalten

Niemals gehören Passwörter, API-Tokens oder SSH-Schlüssel im Klartext in die .gitlab-ci.yml. Stattdessen hinterlegst du sie als CI/CD-Variablen in den Projekteinstellungen (Settings → CI/CD → Variables). Dort lassen sie sich als "protected" (nur für geschützte Branches) und "masked" (im Job-Log unkenntlich gemacht) markieren.

Für besonders sensible Umgebungen unterstützt GitLab auch die Integration externer Secret-Manager wie HashiCorp Vault. Wenn du sichere Tokens oder zufällige Geheimnisse für deine Variablen brauchst, hilft dir unser Passwort-Generator beim Erzeugen kryptografisch starker Werte. Weitere praktische Helfer für den Entwickleralltag findest du im Webtools-Bereich.

Vom Build zum Deployment

Wie das eigentliche Deployment aussieht, hängt von deinem Ziel ab. Verbreitete Muster sind:

  • Container-Image bauen und pushen: Im Build-Job ein Docker-Image erstellen und in die GitLab Container Registry oder eine andere Registry pushen.
  • Deployment per SSH: Über einen hinterlegten SSH-Key auf den Zielserver verbinden und dort das neue Image ziehen und starten.
  • Kubernetes-Deployment: Mit kubectl oder Helm das aktualisierte Manifest auf den Cluster anwenden.
  • PaaS-Integration: Über ein CLI-Tool des Anbieters direkt deployen.

GitLab bietet zudem das Konzept der Environments, mit dem du Deployments nach Umgebung (Staging, Production) gruppierst und im UI nachverfolgst, welche Version gerade wo läuft – inklusive Rollback-Möglichkeit auf eine vorherige Version.

Best Practices für robuste Pipelines

  • Fail fast: Lege schnelle Checks (Linting, Unit-Tests) in frühe Stages, damit Fehler sofort auffallen und die Pipeline früh abbricht.
  • Pipelines schlank halten: Nutze Caching konsequent und vermeide unnötige Schritte. Lange Pipelines bremsen das ganze Team aus.
  • Reproduzierbarkeit: Pinne Image-Versionen exakt (node:20.11-alpine statt node:latest), damit Builds heute wie in einem Jahr identisch laufen.
  • DRY mit Templates: Wiederkehrende Job-Definitionen lassen sich mit extends und versteckten Jobs (mit führendem Punkt) auslagern und wiederverwenden.
  • Aussagekräftige Logs: Sorge dafür, dass fehlgeschlagene Jobs klar sagen, was schiefging – das spart später viel Sucherei.

Häufige Fragen

Was ist der Unterschied zwischen CI und CD?

Continuous Integration (CI) meint das automatische Bauen und Testen bei jeder Änderung, damit Integrationsprobleme früh auffallen. Continuous Delivery/Deployment (CD) erweitert das um die automatisierte Auslieferung – bei Delivery bis zu einem freigabebereiten Stand, bei Deployment vollautomatisch bis in die Produktion.

Ist GitLab CI/CD kostenlos?

Die CI/CD-Funktion selbst ist Teil von GitLab, auch in der Free-Stufe. Auf gitlab.com gibt es ein monatliches Kontingent an Runner-Minuten in der kostenlosen Variante; darüber hinaus oder mit eigenen Runnern fallen entsprechende Kosten an. Eine selbst gehostete GitLab-Instanz mit eigenen Runnern verursacht nur deine Infrastrukturkosten.

Wie unterscheidet sich GitLab CI/CD von GitHub Actions?

Beide lösen dasselbe Problem mit ähnlichen Konzepten. GitLab CI/CD ist eng in die GitLab-Plattform integriert und nutzt eine einzelne .gitlab-ci.yml. GitHub Actions setzt stärker auf einen Marktplatz wiederverwendbarer Actions. Welches besser passt, hängt vor allem davon ab, welche Plattform du ohnehin nutzt.

Warum schlägt meine Pipeline fehl, obwohl der Code lokal funktioniert?

Meist liegt es an Umgebungsunterschieden: andere Abhängigkeitsversionen, fehlende Umgebungsvariablen oder Annahmen über lokal vorhandene Dateien. Genau deshalb laufen Jobs in sauberen Containern – das deckt versteckte Abhängigkeiten von deinem lokalen Setup auf. Prüfe das Job-Log genau, oft steht die Ursache direkt darin.

Arthur Hardy Kotsch
Über den Autor
Arthur Hardy Kotsch

Gründer der Softwaremarke Kotsch.Tech, B.Eng. Digital Engineering, aktuell im MBA-Studium Production Management (TU Chemnitz). Entwickelt 34 Apps im Apple App Store sowie Android-Apps, Windows-Programme und Web-Anwendungen.