Jenkins mit Docker installieren: Der bewährteste Open-Source-CI/CD-Server
Jenkins ist mit über 1.800 Plugins der universellste CI/CD-Server. Diese Anleitung zeigt, wie du ihn per Docker Compose in etwa 20 Minuten betriebsbereit bekommst – mit compose.yaml, .env, initialem Setup-Wizard und Verifikation nach jedem Schritt.

Jenkins ist seit Jahren der meistgenutzte Open-Source-Automationsserver im CI/CD-Bereich. Mit über 1.800 verfügbaren Plugins lässt er sich an nahezu jeden Build-, Test- und Deploy-Workflow anpassen – ob einfache Freestyle-Jobs, deklarative Pipelines (Jenkinsfile), Multi-Branch-Pipelines oder verteilte Build-Agenten. Wer als Team maximale Flexibilität und vollständige Kontrolle über seine Automatisierungspipelines braucht, findet in Jenkins ein bewährtes Fundament. Das offizielle Docker-Image jenkins/jenkins:lts-jdk21 läuft plattformneutral auf Linux (amd64 und arm64) und ist für den Betrieb via Docker Compose optimiert – kein separater Datenbankserver notwendig.
Voraussetzungen
- Docker Engine ≥ 20.10 und das Docker Compose Plugin v2 (
docker composeohne Bindestrich) müssen auf dem Host installiert sein. Eine vollständige Installationsanleitung findest du unter Docker und Docker Compose auf Linux installieren. - Ein Linux-Host, eine VM oder ein NAS mit Docker-Unterstützung – die Anleitung funktioniert auf Ubuntu, Debian und jedem anderen System mit Docker Engine (auch ARM64, z. B. Raspberry Pi 4/5 oder Apple Silicon).
- Mindestens 1 GB RAM, empfohlen 2–4 GB für produktive Builds; mindestens 5 GB freier Speicherplatz (Workspaces und Build-Artefakte wachsen über die Zeit).
- Internetzugang für den initialen Plugin-Download (ca. 200–500 MB je nach Auswahl im Setup-Wizard).
- Für HTTPS-Zugang von außen empfiehlt sich ein Reverse Proxy; eine bewährte Lösung zeigt die Anleitung Traefik als Docker-Reverse-Proxy mit automatischem HTTPS.
Schritt 1: Projektordner anlegen
Lege einen dedizierten Ordner für den Jenkins-Stack an. Ein Unterverzeichnis unter /opt/ ist für systemweite Dienste üblich; im Home-Verzeichnis geht es genauso.
mkdir -p /opt/jenkins
cd /opt/jenkinsDer Ordner enthält ausschließlich compose.yaml und .env. Das Jenkins-Datenverzeichnis (jenkins_home) verwaltet Docker als Named Volume – kein Bind-Mount-Berechtigungsproblem.
Verifizieren: ls /opt/jenkins – der Ordner existiert (zunächst leer, was korrekt ist).
Schritt 2: .env-Datei anlegen
Die .env-Datei enthält alle Konfigurationsparameter, die du ohne Änderung an der compose.yaml anpassen kannst. Da Jenkins keine Datenbankpasswörter oder Secret-Keys in Umgebungsvariablen benötigt, ist die Datei bewusst schlank.
# Jenkins – Konfiguration
# Port, auf dem Jenkins im Browser erreichbar ist
JENKINS_HTTP_PORT=8080
# Port fuer eingehende Build-Agenten (JNLP) – nur benoetigt wenn externe Nodes verbunden werden
JENKINS_AGENT_PORT=50000
# Java VM Optionen: Zeitzone und Heap-Groesse (anpassen bei wenig RAM: -Xmx1g -Xms256m)
JAVA_OPTS=-Duser.timezone=Europe/Berlin -Xmx2g -Xms512m
# Jenkins-Startargumente (leer lassen fuer Standard; Beispiel fuer Reverse-Proxy: --prefix=/jenkins)
JENKINS_OPTS=Verifizieren: cat /opt/jenkins/.env – alle vier Variablen sind sichtbar, keine Syntaxfehler (kein Leerzeichen um das =-Zeichen).
Schritt 3: compose.yaml erstellen
Die folgende compose.yaml verwendet das offizielle LTS-Image mit JDK 21, ein Named Volume für Datenpersistenz und einen Healthcheck, der Jenkins' verzögerten Start berücksichtigt.
services:
jenkins:
image: jenkins/jenkins:lts-jdk21
container_name: jenkins
restart: on-failure
ports:
- "${JENKINS_HTTP_PORT:-8080}:8080"
- "${JENKINS_AGENT_PORT:-50000}:50000"
volumes:
- jenkins_home:/var/jenkins_home
environment:
- JAVA_OPTS=${JAVA_OPTS:--Duser.timezone=Europe/Berlin -Xmx2g -Xms512m}
- JENKINS_OPTS=${JENKINS_OPTS:-}
- JENKINS_SLAVE_AGENT_PORT=50000
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:8080/login || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 120s
volumes:
jenkins_home:
driver: localWichtige Details zur Konfiguration im Überblick:
| Parameter | Wert | Hinweis |
|---|---|---|
| Image | jenkins/jenkins:lts-jdk21 | LTS + OpenJDK 21 – empfohlenes Produktions-Tag; Alternative: lts-jdk17 |
| Port 8080 | Web-UI (Pflicht) | Haupt-Zugriff für Browser und REST-API |
| Port 50000 | Agenten-Port (optional) | Nur benötigt wenn externe Build-Nodes per JNLP angebunden werden |
Volume jenkins_home | /var/jenkins_home | Speichert Konfiguration, Plugins, Workspaces und Build-Logs dauerhaft |
| UID/GID | 1000/1000 | Named Volume: Docker setzt Berechtigungen automatisch; Bind Mount: chown 1000:1000 vorab |
| Datenbank | keine | Jenkins ist dateibasiert – kein PostgreSQL/MySQL erforderlich |
Verifizieren: cat /opt/jenkins/compose.yaml – YAML ohne Einrückungsfehler, Image-Name korrekt (jenkins/jenkins:lts-jdk21, nicht das veraltete jenkins-Image ohne Namespace).
Schritt 4: Jenkins starten
Starte Jenkins im Hintergrund. Der erste Start dauert 2–3 Minuten, da das Image geladen und Jenkins initialisiert wird.
cd /opt/jenkins
docker compose up -dVerfolge die Logs während des Starts:
docker compose logs -f jenkinsJenkins ist startbereit, wenn du in den Logs folgende Zeile siehst:
Jenkins is fully up and runningVerifizieren: docker compose ps – der Container jenkins zeigt Up (nach ca. 2 Minuten auch healthy). Außerdem:
curl -sf http://localhost:8080/login && echo "OK" || echo "Noch nicht bereit"Erwartete Ausgabe nach vollständigem Start: OK. Solange Jenkins noch hochfährt, gibt curl einen Fehler zurück – das ist normal und durch den start_period-Parameter im Healthcheck berücksichtigt.
Schritt 5: Initiales Admin-Passwort abrufen
Beim ersten Start generiert Jenkins automatisch ein zufälliges Admin-Passwort und speichert es in /var/jenkins_home/secrets/initialAdminPassword. Du brauchst es für den Setup-Wizard.
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPasswordAlternativ findest du das Passwort prominent in den Container-Logs:
docker compose logs jenkins | grep -A 5 "Please use the following password"Die Ausgabe sieht etwa so aus:
*************************************************************
Jenkins initial setup is required. An admin user has been created
and a password generated.
Please use the following password to proceed to installation:
a1b2c3d4e5f6789012345678abcdef01
*************************************************************Notiere diesen 32-stelligen hexadezimalen String – du benötigst ihn einmalig im nächsten Schritt.
Verifizieren: Wenn docker exec fehlschlägt, ist Jenkins noch nicht vollständig gestartet – kurz warten und wiederholen. Das Passwort ist stets genau 32 Zeichen lang.
Schritt 6: Setup-Wizard im Browser abschließen
Öffne http://<HOST-IP>:8080 im Browser (oder http://localhost:8080 lokal). Der Setup-Wizard führt dich durch drei Schritte:
- Jenkins entsperren: Gib das initiale Admin-Passwort aus Schritt 5 ein und klicke auf „Continue".
- Plugins installieren: Wähle „Install suggested plugins" – Jenkins installiert die empfohlenen Plugins (Pipeline, Git, Credentials, Blue Ocean u. a.). Dieser Schritt dauert 5–10 Minuten und benötigt Internetzugang.
- Admin-Account erstellen: Lege einen Benutzernamen, ein sicheres Passwort und eine E-Mail-Adresse für den administrativen Account fest. Klicke auf „Save and Finish".
Nach Abschluss des Wizards startet Jenkins und ist vollständig einsatzbereit.
Verifizieren: Nach dem Setup-Wizard erscheint das Jenkins-Dashboard. Navigiere zu „Manage Jenkins → System Information" – dort sind alle aktiven Plugins und Systemparameter aufgelistet. Im Terminal:
curl -I http://localhost:8080/
# Erwartete Antwort: HTTP/1.1 200 OK (oder 403 bei aktivierter Login-Pflicht – beide korrekt)Schritt 7: Erster Pipeline-Job anlegen (optional)
Um zu prüfen, ob Jenkins korrekt arbeitet, lege einen einfachen Test-Job an. Klicke im Dashboard auf „New Item", wähle „Pipeline" und vergib einen Namen, z. B. test-pipeline. Im „Pipeline"-Reiter gibst du folgendes Jenkinsfile direkt ein:
pipeline {
agent any
stages {
stage('Hello') {
steps {
echo 'Jenkins laeuft korrekt!'
}
}
}
}Klicke auf „Save" und dann „Build Now". Der Build sollte nach wenigen Sekunden mit blauer Kugel (Erfolg) abschließen.
Verifizieren: Im Build-Log unter „Console Output" erscheint die Ausgabe Jenkins laeuft korrekt! und der Build zeigt Status „SUCCESS".
Schritt 8: Updates durchführen
Jenkins-Updates sind denkbar einfach – alle Daten bleiben im Named Volume erhalten. Plane vor jedem Update dennoch ein Backup des Volumes ein.
cd /opt/jenkins
docker compose pull
docker compose up -dDocker lädt das neue LTS-Image, stoppt den alten Container und startet einen neuen. Das Volume jenkins_home bleibt unberührt.
Verifizieren:
docker compose ps
# STATUS: Up (healthy)
docker inspect jenkins --format='{{.Config.Image}}'
# Zeigt das aktuell verwendete Image-TagBackup des Jenkins-Volumes
Da Jenkins alle Daten in /var/jenkins_home ablegt, reicht ein Backup des Named Volumes für eine vollständige Datensicherung:
# Container stoppen (empfohlen fuer konsistentes Backup)
docker compose down
# Volume-Inhalt als tar.gz sichern
docker run --rm \
-v jenkins_home:/data:ro \
-v /opt/backups:/backup \
alpine tar czf /backup/jenkins_home_$(date +%Y%m%d).tar.gz -C /data .
# Container wieder starten
docker compose up -dEine systematische Backup-Strategie mit Rotation und Off-Site-Kopie beschreibt die Anleitung 3-2-1-Backup-Strategie umsetzen.
Troubleshooting / Typische Fehler
- Container startet und stoppt sofort – Logs zeigen
java.lang.OutOfMemoryError: Zu wenig RAM. Passe in der.envden WertJAVA_OPTSan:-Xmx1g -Xms256mfür Hosts mit 1–2 GB RAM. Mindestens 1 GB sollte für Jenkins reserviert sein. - Web-UI nach dem Start nicht erreichbar: Jenkins benötigt 2–3 Minuten zum vollständigen Hochfahren.
docker compose logs -f jenkinszeigt den Fortschritt. Erst wenn „Jenkins is fully up and running" erscheint, ist Port 8080 bereit. - Initiales Passwort nicht gefunden: Prüfe mit
docker exec jenkins ls /var/jenkins_home/secrets/ob die DateiinitialAdminPasswordexistiert. Wenn nicht, ist Jenkins noch nicht fertig initialisiert – kurz warten. - Permission denied auf
/var/jenkins_homebei Bind Mount: Wenn du statt des Named Volumes einen Bind Mount nutzt (./jenkins_home:/var/jenkins_home), muss das Host-Verzeichnis vorab angelegt werden:mkdir -p ./jenkins_home && chown 1000:1000 ./jenkins_home. Mit Named Volumes (empfohlene Methode) entfällt dieses Problem. - Plugin-Installation schlägt beim Setup-Wizard fehl: Jenkins versucht Plugins vom Update-Center zu laden. Bei eingeschränktem Internetzugang oder Proxy:
JAVA_OPTSin der.envum-Dhttps.proxyHost=proxy.intern -Dhttps.proxyPort=3128ergänzen. - Reverse-Proxy-Warnung „It appears that your reverse proxy set up is broken": Beim Betrieb hinter nginx oder Traefik müssen die Header
X-Forwarded-For,X-Forwarded-ProtoundX-Forwarded-Hostkorrekt weitergeleitet werden. ZusätzlichJENKINS_OPTS=--prefix=/jenkinssetzen, wenn Jenkins unter einem Subpfad läuft. - Veraltetes Image
jenkins(ohne Namespace) verwendet: Das Image unterhub.docker.com/_/jenkinsist seit Jahren als „deprecated" markiert und hat bekannte Sicherheitslücken. Ausschließlichjenkins/jenkins:lts-jdk21verwenden. - Datenverlust nach
docker compose down -v: Das Flag-vlöscht alle Volumes. Niedown -vausführen, solange keine Datensicherung vorliegt. Dervolumes-Block in dercompose.yamlstellt sicher, dass ein Named Volume (kein anonymes) verwendet wird.
Häufige Fragen
Braucht Jenkins eine Datenbank wie PostgreSQL oder MySQL?
Nein. Jenkins ist ein dateibasiertes System und speichert die gesamte Konfiguration, alle Plugins, Workspaces und Build-Logs im Verzeichnis /var/jenkins_home. Eine externe Datenbank ist für die Standardinstallation weder erforderlich noch empfohlen.
Wie bekomme ich das initiale Admin-Passwort?
Es gibt zwei Wege: Entweder direkt aus dem Container mit docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword oder aus den Logs mit docker compose logs jenkins | grep -A 2 "password". Das Passwort erscheint beim ersten Start prominent in den Logs und ist 32 Zeichen lang (hexadezimal).
Wie installiere ich Plugins automatisch ohne Setup-Wizard?
Über ein eigenes Dockerfile: FROM jenkins/jenkins:lts-jdk21 und dann RUN jenkins-plugin-cli --plugins pipeline-model-definition github-branch-source. Dieses Muster eignet sich für unveränderliche Deployments, bei denen der Setup-Wizard nicht interaktiv durchlaufen werden kann.
Kann Jenkins auf einem Raspberry Pi oder ARM-Server laufen?
Ja. Das offizielle Image jenkins/jenkins:lts-jdk21 ist ein Multiarch-Image und unterstützt nativ linux/arm64 (aarch64). Auf einem Raspberry Pi 4 oder 5 mit 64-Bit-Betriebssystem läuft das Standard-Image ohne jegliche Anpassungen. Für den Pi empfiehlt sich mindestens das 4-GB-RAM-Modell.
Wie verbinde ich externe Build-Agenten (Nodes)?
Port 50000 muss vom Agenten-Host erreichbar sein (ggf. in der Firewall freigeben). In Jenkins unter „Manage Jenkins → Nodes → New Node" einen neuen Agenten anlegen, den JNLP-Startbefehl kopieren und auf dem Agenten-Host ausführen. Der Agenten-Host benötigt Java und Netzwerkzugang zu Jenkins auf Port 50000.
Wie aktualisiere ich Jenkins auf eine neue LTS-Version?
Da das Tag lts-jdk21 automatisch auf die neueste LTS-Version zeigt, reicht docker compose pull && docker compose up -d. Alle Daten im Volume bleiben erhalten. Vor jedem Update das Volume sichern – danach bei Bedarf unter „Manage Jenkins → Manage Plugins" etwaige Plugin-Updates abschließen.
Was ist der Unterschied zwischen Jenkins und Woodpecker CI?
Jenkins ist das flexibelste und ausgereifteste System mit über 1.800 Plugins – ideal für komplexe Anforderungen und heterogene Technologie-Stacks. Für schlanke, Pipeline-as-Code-zentrierte Setups ohne Plugin-Overhead ist Woodpecker CI mit Docker eine interessante leichtgewichtige Alternative.
Fazit
Jenkins per Docker Compose zu betreiben ist überraschend unkompliziert: eine compose.yaml, eine .env und docker compose up -d – fertig. Das Named Volume erledigt die Berechtigungsproblematik automatisch, der Healthcheck berücksichtigt Jenkins' längere Startzeit, und LTS-Updates sind auf drei Befehle reduziert. Der initiale Setup-Wizard mag für Einsteiger nach vielen Klicks aussehen, er ist aber einmalig und danach vollständig scriptbar.
Der eigentliche Mehrwert von Jenkins liegt in den 1.800+ Plugins und der Jenkinsfile-Syntax: Sobald Build-Pipelines als Code in der Versionsverwaltung liegen, werden Deployments reproduzierbar, nachvollziehbar und teamtauglich. Wer darüber hinaus Container-Images innerhalb von Pipelines bauen will, kann Docker-in-Docker (dind) als separaten Compose-Service hinzufügen – das ist jedoch ein optionaler Fortgeschrittenen-Schritt, der für die Basis-Installation nicht notwendig ist.
Für Secrets-Management, Non-Root-Container und sichere Healthcheck-Konfiguration in der Produktion lohnt sich ein Blick in Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only.
Weiterführende Anleitungen und Quellen
- Docker und Docker Compose auf Linux installieren (Ubuntu/Debian) – die Self-Hosting-Grundlage
- Traefik als Docker-Reverse-Proxy mit automatischem HTTPS – Jenkins sicher über HTTPS erreichbar machen
- Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only
- Woodpecker CI mit Docker installieren: schlanke CI/CD-Pipeline – leichtgewichtige Alternative
- 3-2-1-Backup-Strategie umsetzen – Jenkins-Volume sicher sichern
Offizielle Quellen: Jenkins-Dokumentation: Installation mit Docker · GitHub: jenkinsci/docker · Docker Hub: jenkins/jenkins