Baue deine erste CI/CD-Pipeline von Grund auf
Der Bau deiner ersten CI/CD-Pipeline kann wie eine entmutigende Aufgabe wirken, besonders wenn die Systeme am Arbeitsplatz komplex und riskant für Experimente sind. Die Kernprinzipien sind jedoch bemerkenswert einfach: Eine Pipeline ist einfach ein automatisierter Prozess, der Abhängigkeiten installiert, Tests ausführt und deine Anwendung in einer sauberen, reproduzierbaren Umgebung erstellt. Dieser Leitfaden führt dich durch die grundlegenden Konzepte und praktischen Schritte, die du benötigst, um eine CI/CD-Pipeline von Grund auf zu bauen und manuelle, fehleranfällige Bereitstellungen in einen zuverlässigen, automatisierten Workflow zu verwandeln.
Du brauchst kein Kubernetes oder ein Produktionssystem, um CI/CD zu üben. Beginne mit einem kleinen Projekt, einem Git-Repository und einem CI-Tool wie GitHub Actions, GitLab CI oder Jenkins. Der wichtigste Schritt ist, sicherzustellen, dass dein Build lokal reproduzierbar ist, bevor du eine einzige Zeile Pipeline-Konfiguration schreibst.
Die Grundlage: Reproduzierbarkeit ist der Schlüssel
Bevor du deine erste Pipeline-Datei schreibst, muss dein Projekt in der Lage sein, von Grund auf sauber zu bauen. Wenn dies bei einem frischen Klon deines Repositorys fehlschlägt, wird es auch in CI fehlschlagen.
Schritt 1: Mache deinen lokalen Build reproduzierbar
Die goldene Regel ist, sicherzustellen, dass deine Anwendung von einem sauberen Zustand auf deinem lokalen Rechner erfolgreich gebaut wird. Zum Beispiel:
- Node.js:
npm ci && npm test && npm run build - Python:
pip install -r requirements.txt && pytest - Go:
go test ./... && go build
Schritt 2: Committe Lock-Dateien
Lock-Dateien (wie package-lock.json, go.sum oder Pipfile.lock) sind für deterministische Builds unerlässlich. Ohne sie könnte deine CI-Pipeline andere Abhängigkeitsversionen installieren als du lokal verwendet hast, was zu unvorhersehbaren Testfehlern führt. In Node.js erzwingt npm ci die Lock-Datei genau und verhindert so diese "Abhängigkeitsdrift".
Deine erste Pipeline schreiben
Mit einem reproduzierbaren Build kannst du ihn jetzt automatisieren. Eine grundlegende Pipeline hat drei Phasen: Build, Test und Deploy.
Schritt 3: Wähle dein CI/CD-Tool
Deine Wahl hängt oft davon ab, wo dein Code lebt. Hier sind drei gängige Optionen:
| Tool | Am besten geeignet für | Pipeline-Definition | Self-Hosted-Option |
|---|---|---|---|
| GitHub Actions | Projekte, die bereits auf GitHub sind, öffentliche Repos (kostenlos). | .github/workflows/*.yml |
Ja (Self-hosted Runner) |
| GitLab CI | All-in-One-DevOps-Plattform mit Git-Hosting. | .gitlab-ci.yml |
Ja (GitLab CE) |
| Jenkins | Hochgradig anpassbar, ausgereiftes Ökosystem, komplexe Build-Logik. | Jenkinsfile (Groovy) |
Ja (über Java, plugin-basiert) |
Schritt 4: Erstelle eine minimale Pipeline-Konfiguration
Die Pipeline-Definition ist eine YAML- oder Groovy-Datei im Stammverzeichnis deines Repositorys, die dem CI-Runner mitteilt, was zu tun ist.
Beispiel: .gitlab-ci.yml (GitLab CI)
Dies definiert eine Pipeline, die eine Go-Anwendung erstellt, die Binärdatei als Artefakt speichert und sie dann in einer späteren Phase ausführt.
default:
image: golang
stages:
- build
- run
build go:
stage: build
script:
- go build
artifacts:
paths:
- array
run go:
stage: run
script:
- ./array
Beispiel: Jenkinsfile (Deklarative Pipeline)
Dies macht dasselbe, indem es ein Docker-Image verwendet, um die Node.js-App auszuführen.
pipeline {
agent { docker { image 'node:20-alpine' } }
stages {
stage('Build') {
steps { sh 'npm ci && npm run build' }
}
stage('Test') {
steps { sh 'npm run test' }
}
}
}
⚠️ Sicherheitswarnung: Hardcode niemals Umgebungsvariablen wie Datenbank-URLs oder API-Schlüssel in deinem Repository. Verwende den integrierten Secrets-Manager deines CI-Tools (GitLab CI Variables, Jenkins Credentials oder GitHub Actions Secrets), um sie in deine Jobs einzufügen.
Daten zwischen Phasen teilen
Eine Schlüsselfunktion moderner Pipelines ist die Möglichkeit, Daten zwischen Jobs zu teilen. Ohne dies müsstest du deine Anwendung in jeder Phase neu erstellen, was Zeit und Ressourcen verschwendet.
Schritt 5: Verwende Artefakte
Artefakte sind Dateien oder Verzeichnisse, die von einem Job gespeichert und nachfolgenden Jobs zur Verfügung gestellt werden. Im GitLab-CI-Beispiel speichert der Job build go die Binärdatei array. Der Job run go lädt diese Binärdatei dann automatisch herunter und verwendet sie, ohne sie neu kompilieren zu müssen.
Bereitstellungen automatisieren (optional)
Sobald CI funktioniert, kannst du Continuous Deployment hinzufügen. Das Prinzip ist einfach: Bereitstellungen sollten nur nach bestandenen Tests erfolgen.
Schritt 6: Implementiere eine grundlegende Bereitstellungsstrategie
Für einfache Anwendungen kann ein SSH-Befehl Dateien auf deinen Server kopieren.
Beispiel: Bereitstellung mit rsync
deploy:
stage: deploy
image: alpine:latest
only:
- main
script:
- apk add --no-cache openssh-client rsync
- rsync -avz --delete dist/ deploy@yourserver:/var/www/app/
Wenn du Container verwendest, erstellt die Deploy-Phase typischerweise ein Docker-Image, pusht es in eine Registry und verwendet dann SSH, um docker compose pull && docker compose up -d auf dem Produktionsserver auszulösen.
Üben und Fehlerbehebung
Über CI/CD zu lesen reicht nicht. Um wirklich zu lernen, musst du Pipelines ausführen und sie absichtlich zum Scheitern bringen.
Schritt 7: Absichtlich Dinge kaputt machen, um zu lernen
Hier entsteht echtes Verständnis. Probiere diese Experimente aus:
- Entferne eine Abhängigkeitsdeklaration. Schlägt CI fehl? Warum?
- Lösche die Lock-Datei. Führen Versionsabweichungen zum Build-Fehler?
- Füge einen flaky Test hinzu. Besteht er lokal, schlägt aber in CI fehl? Das deckt oft Unterschiede in der sauberen CI-Umgebung auf.
Schritt 8: Verwende Testberichte und Logs
CI sollte Einblick geben, welche Tests fehlgeschlagen sind, welche langsam sind und welche flaky sind. Nutze die Logs nicht nur, um Fehler zu finden, sondern um den gesamten Prozess zu verstehen: Wie lange dauert die Abhängigkeitsinstallation? Wo genau schlägt der Build fehl?
Häufig gestellte Fragen
Wie lange dauert es, meine erste CI/CD-Pipeline zu bauen? Für ein einfaches Projekt kannst du in weniger als einer Stunde eine grundlegende Pipeline zum Laufen bringen. Das GitLab-CI-Praxislabor schätzt 15 Minuten für eine grundlegende Pipeline. Die Zeit wird normalerweise für das Schreiben der Konfigurationsdatei und die Fehlerbehebung bei Reproduzierbarkeitsproblemen aufgewendet.
Sollte ich als Anfänger Jenkins, GitHub Actions oder GitLab CI wählen? Wenn dein Code auf GitHub ist, ist GitHub Actions eine natürliche Wahl. Für eine All-in-One-Plattform ist GitLab CI hervorragend. Jenkins ist unglaublich leistungsstark, hat aber eine steilere Lernkurve und erfordert mehr Wartung, daher ist es oft besser für größere, komplexere Setups geeignet.
Was ist der Unterschied zwischen einem Artefakt und einem Cache in CI/CD?
Artefakte werden verwendet, um Dateien zwischen Phasen zu übergeben (z.B. Übergabe einer kompilierten Binärdatei von der Build-Phase an die Deploy-Phase). Caches werden verwendet, um Builds zu beschleunigen, indem Dateien wie Abhängigkeiten (node_modules) über verschiedene Pipeline-Läufe hinweg wiederverwendet werden.
Warum bestehen meine Tests lokal, schlagen aber in der CI-Pipeline fehl? Dies ist normalerweise ein Zeichen für Umgebungsdrift. Dein lokaler Rechner kann andere Softwareversionen oder Umgebungsvariablen haben. Deshalb sind Lock-Dateien entscheidend und warum es ein notwendiger erster Schritt ist, dein Projekt von einem sauberen Klon lokal auszuführen.
Brauche ich Docker, um eine CI/CD-Pipeline zu bauen? Nicht unbedingt, aber es wird dringend empfohlen. Das Ausführen von Jobs in Docker-Containern gewährleistet Isolation und Reproduzierbarkeit. Es garantiert, dass jeder Job in einer sauberen, bekannten Umgebung läuft und verhindert, dass Jobs sich gegenseitig stören oder den Host-Server verschmutzen.
— Editorial Team
Noch keine Kommentare.