Docker-Container startet und beendet sich sofort? Vollständige Troubleshooting-Anleitung (inkl. Exit-Codes 137/1)

Gerade wollte ich den Rechner zum Feierabend ausschalten, als mein Handy vibrierte – Alarm in der Produktionsumgebung. Ein Blick aufs Display: Alle vier Kernservices waren im Exited-Status. Terminal auf, docker ps eingegeben. Leer. Komplett leer.
Das Gefühl ist wie beim Öffnen des Kühlschranks für ein Getränk – und der Kühlschrank ist völlig leer. Panik.
Ehrlich gesagt war mein erster Gedanke: „Schluss, das Wochenende ist gelaufen.” Aber nach kurzer Ruhe wurde mir klar: Container-Startfehler sind kein Neuland. Diesmal kam das Problem nur plötzlicher und mit größerer Wirkung.
Nach über zwei Stunden Fehlersuche stellte sich heraus, dass die Ursache simpel war – ein falscher Pfad in einer Service-Konfigurationsdatei, wodurch die Datenbankverbindung scheiterte und der Container sofort beendet wurde. Mit einem systematischen Troubleshooting-Workflow wäre das Problem vermutlich in zehn Minuten gelöst gewesen.
Dieser Artikel ist meine Zusammenfassung aus unzähligen Fehlversuchen: eine Anleitung zur Fehlerbehebung bei fehlgeschlagenen Container-Starts. Ob Exit Code 1, 137 oder ein anderer Code – diese Methode hilft Ihnen, die Ursache schnell zu finden.
Container-Lebenszyklus und Exit-Codes verstehen
Bevor wir mit der Fehlersuche beginnen, klären wir eine Grundfrage: Warum beendet sich ein Container?
Das Wesen eines Containers: Lebenszyklus eines Prozesses
Ein Docker-Container ist im Grunde ein isolierter Prozess. Läuft der Prozess, läuft der Container; beendet sich der Prozess, ist der Container beendet.
Stellen Sie sich vor, Sie starten einen Web-Service-Container. Der Hauptprozess darin ist vielleicht nginx oder node – solange er läuft, erscheint der Container in docker ps. Beendet sich der Hauptprozess – normal, durch Absturz oder durch das System – wechselt der Container sofort in den Exited-Status.
Deshalb zeigt docker ps manchmal nichts an; erst mit -a sehen Sie auch beendete Container.
Exit-Code-Referenz: Was die Zahlen bedeuten
Bei jedem Container-Exit speichert Docker einen Exit-Code. Die Zahl wirkt kryptisch, erzählt aber, was passiert ist.
Exit Code 0: Alles in Ordnung, Aufgabe abgeschlossen.
Beispiel: Ein Datenimport-Skript läuft durch und beendet sich – Exit Code 0. Kein Fehler, der Container hat seine Aufgabe erledigt.
Exit Code 1: Die Anwendung selbst ist fehlgeschlagen.
Der häufigste Fehlercode. Mögliche Ursachen: falsche Konfiguration, fehlende Abhängigkeit oder Bug im Code – die Anwendung im Container ist abgestürzt.
Ich erinnere mich an ein MySQL-Deployment mit permanentem Exit Code 1. Nach langem Log-Studium stellte sich heraus: In der Konfigurationsdatei hatte ich aus Versehen ein Gleichheitszeichen durch einen Doppelpunkt ersetzt. MySQL startete, erkannte den Syntaxfehler und beendete sich sofort.
Exit Code 137: Speichermangel oder erzwungene Beendigung.
Dieser Code macht mir am meisten Sorgen. 137 bedeutet meist:
- Der Container hat zu viel Speicher verbraucht – der Linux-OOM Killer (Out-of-Memory Killer) hat den Prozess beendet
- Jemand (oder das System) hat
docker killoderkill -9ausgeführt
Wie unterscheiden? Mit docker inspect das Feld OOMKilled prüfen. Bei true liegt ein Speicherproblem vor; bei false eher eine manuelle Beendigung.
Exit Code 127: Befehl nicht gefunden.
Typisch bei falschem Pfad in CMD oder ENTRYPOINT im Dockerfile, oder wenn die ausführbare Datei im Image fehlt.
Exit Code 139: Segmentation Fault.
Tritt meist bei C/C++-Programmen auf – Zugriff auf ungültigen Speicher. Bei normalen Anwendungen selten.
Muster bei Exit-Codes
Exit-Codes folgen einer Logik:
- 0: Normaler Exit, kein Problem
- 1–128: Fehler der Anwendung selbst (Anwendungs- oder Konfigurationsfehler)
- 129–255: Externe Eingriffe (Signal-Unterbrechung, Beendigung durch das System)
Mit diesem Wissen können Sie den Exit-Code grob einordnen und die Fehlersuche gezielt starten.
Vier-Schritte-Methode zur schnellen Fehlerfindung
Sie kennen jetzt die Bedeutung der Exit-Codes. Aber das allein reicht nicht – Sie brauchen einen klaren Ablauf.
Ich habe eine Vier-Schritte-Methode entwickelt, die etwa 90 % der Container-Startfehler abdeckt. Wenn Sie diesem Ablauf folgen, wirken die Probleme weniger undurchsichtig.
Schritt 1: Container-Status bestätigen
Bevor Sie in die Logs schauen: Bestätigen Sie, dass der Container existiert und beendet ist.
docker ps -a
Dieser Befehl listet alle Container, auch beendete. Achten Sie auf:
CONTAINER ID: Eindeutige Kennung für alle folgenden Befehle. Die ersten Zeichen reichen – Docker matcht automatisch.
Spalte STATUS: Hier liegt der Schlüssel. Laufende Container zeigen Up X minutes, beendete Exited (Exit-Code) X minutes ago.
Beispiel:
CONTAINER ID IMAGE STATUS
a1b2c3d4e5f6 mysql:8.0 Exited (1) 2 minutes ago
Exit-Code 1 deutet auf Anwendungsebene hin; 137 eher auf Speicherprobleme.
Erstellungs- und Exit-Zeit beachten. Beendet sich der Container weniger als eine Sekunde nach dem Start, liegt meist ein Problem mit Startbefehl oder Konfiguration vor. Läuft er eine Weile und bricht dann ab, eher Ressourcenmangel oder ausgefallene Abhängigkeiten.
Schritt 2: Container-Logs prüfen
Der wichtigste Schritt. Vor dem Exit hinterlässt der Container meist Spuren – in den Logs.
Grundlegende Anzeige:
docker logs <container_id>
Zeigt stdout und stderr. Oft sehen Sie direkt Fehlermeldungen wie Permission denied, No such file or directory oder Connection refused.
Echtzeit-Verfolgung (für den Startvorgang):
docker logs -f <container_id>
Mit -f folgen Sie neuen Logzeilen wie bei tail -f. Bei bereits beendeten Containern weniger nützlich – eher beim erneuten Startversuch.
Nur die letzten Zeilen:
docker logs --tail 100 <container_id>
Bei langen Logs reichen oft die letzten 100 Zeilen – dort steht meist der entscheidende Hinweis.
Mit Zeitstempel:
docker logs -t <container_id>
-t fügt jedem Logeintrag einen Zeitstempel hinzu – hilfreich für die zeitliche Einordnung.
Fehler filtern:
docker logs <container_id> 2>&1 | grep -i error
Bei vielen Logzeilen: nur Einträge mit „error” anzeigen – schneller Fokus auf das Wesentliche.
Schritt 3: Container-Konfiguration prüfen
Manchmal reichen die Logs nicht – dann tiefer in Konfiguration und Zustand schauen.
Vollständige Konfiguration:
docker inspect <container_id>
Gibt umfangreiches JSON aus: Konfiguration, Umgebungsvariablen, Mounts, Netzwerk und mehr. Viel Information, aber sehr hilfreich.
Gezielt einzelne Felder abfragen:
Exit-Code anzeigen:
docker inspect --format '{{.State.ExitCode}}' <container_id>
OOM-Kill prüfen:
docker inspect --format '{{.State.OOMKilled}}' <container_id>
Bei Ausgabe true ist Speichermangel bestätigt.
Umgebungsvariablen anzeigen:
docker inspect --format '{{.Config.Env}}' <container_id>
Häufige Fehlerquelle: falsche DB-Verbindungsstrings, API-Keys usw.
Mount-Pfade anzeigen:
docker inspect --format '{{.Mounts}}' <container_id>
Prüfen, ob Konfigurations- und Datenverzeichnisse korrekt gemountet sind.
Log-Dateipfad anzeigen:
docker inspect --format='{{.LogPath}}' <container_id>
Falls docker logs nicht hilft, Log-Datei direkt auf dem Host lesen.
Schritt 4: Interaktiver Start zur Verifikation
Wenn die ersten drei Schritte nicht reichen: selbst in den Container schauen.
Interaktiver Start:
War der ursprüngliche Befehl:
docker run -d my-app
ersetzen Sie -d durch -it für Vordergrund-Ausführung:
docker run -it my-app
So sehen Sie alle Ausgaben während des Starts direkt auf dem Bildschirm.
Manuell in den Container wechseln:
Startet und beendet sich der Container sofort, mit Shell interaktiv starten:
docker run -it my-app /bin/bash
oder:
docker run -it my-app /bin/sh
Im Container können Sie:
- Konfigurationsdateien prüfen:
ls /etc/app/config.yaml - Konfigurationssyntax testen: z. B. bei MySQL
mysqld --verbose --help - Startbefehl manuell ausführen und Fehler beobachten
- Abhängigkeiten testen:
ping database,telnet redis 6379
Besonders geeignet für Pfad-, Berechtigungs- und Abhängigkeitsprobleme.
Klingt nach vielen Schritten – in der Praxis löst Schritt 2 (Logs) die meisten Fälle. Nur bei hartnäckigen Problemen lohnt sich der vollständige Durchlauf.
Fünf typische Fehlerszenarien und Lösungen
Nach der Methode folgen die häufigsten Praxisfälle – fünf Kategorien, die den Großteil der Alltagsprobleme abdecken.
Szenario 1: Fehlerhafte Konfiguration oder fehlender Pfad
Typische Anzeichen:
- Exit Code 1
- Logs mit
No such file or directory,config file not found,syntax erroro. Ä.
Praxisbeispiel:
Bei einem Node.js-Deployment startete der Container nicht. Im Log stand:
Error: ENOENT: no such file or directory, open '/app/config/prod.json'
Ursache: Im docker run war der Mount-Pfad falsch:
-v /home/user/config:/app/conf # hier conf statt config
Die Anwendung erwartete /app/config – ein Buchstabe Unterschied, und der Start scheiterte.
Troubleshooting:
docker inspect --format '{{.Mounts}}'– Mount-Pfade prüfen- Im Container mit
lsprüfen, ob die Datei am erwarteten Ort liegt - Bei Syntaxfehlern in Konfigurationsdateien zeigt die Anwendung meist die betroffene Zeile im Log
Lösungen:
Falscher Mount-Pfad:
# Falsch
docker run -v /host/path:/wrong/path my-app
# Richtig
docker run -v /host/path:/app/config my-app
Syntaxfehler in Konfigurationsdateien:
- YAML: Online-Tools oder
yamllint - JSON: mit
jqvalidieren:jq . config.json - MySQL: im Container
mysqld --verbose --helpausführen
Szenario 2: Speichermangel (OOM Killed)
Typische Anzeichen:
- Exit Code 137
docker inspect --format '{{.State.OOMKilled}}'lieferttrue- Logs mit
Cannot allocate memory,Out of memoryo. Ä.
Praxisbeispiel:
Eine Java-Anwendung lief lokal einwandfrei, auf dem Testserver startete sie ständig neu. Im Log:
OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory failed; error='Cannot allocate memory' (errno=12)
Docker Desktop war auf 512 MB begrenzt – die Java-App benötigte beim Start etwa 600 MB.
Troubleshooting:
# OOM bestätigen
docker inspect --format '{{.State.OOMKilled}}' <container_id>
# Host-Speicher prüfen
free -h
# Speichernutzung des Containers
docker stats <container_id>
Lösungen:
Speicherlimit erhöhen:
docker run -m 1g my-app # max. 1 GB
docker run -m 512m --memory-swap 1g my-app # inkl. Swap
Bei Docker Desktop:
- macOS: Docker Desktop → Preferences → Resources → Memory
- Windows: Docker Desktop → Settings → Resources → Memory
Anwendung optimieren:
- Java: JVM-Heap begrenzen:
java -Xmx512m -jar app.jar - Node.js:
node --max-old-space-size=512 app.js - Code auf Speicherlecks prüfen
Produktionsempfehlung:
- Speicherlimit passend zum tatsächlichen Bedarf setzen
--memory-reservationals Soft-Limit- Speichertrend überwachen und rechtzeitig skalieren
Szenario 3: Portkonflikt
Typische Anzeichen:
- Exit Code 1
- Logs mit
port is already allocated,address already in use,bind: address already in use
Praxisbeispiel:
Montagmorgen: docker-compose up, Nginx-Container startet nicht:
Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use
Freitag war ein lokaler Nginx-Test offen geblieben – Port 80 belegt, neuer Container konnte nicht starten.
Troubleshooting:
Portbelegung prüfen (Linux/macOS):
lsof -i :8080
netstat -tuln | grep 8080
Portbelegung prüfen (Windows):
netstat -ano | findstr 8080
Port-Mappings anderer Container:
docker ps --format "table {{.Names}}\t{{.Ports}}"
Lösungen:
Option 1: Anderes Host-Port-Mapping
# Ursprünglich
docker run -p 8080:8080 my-app
# Anderen Port wählen
docker run -p 8081:8080 my-app
Option 2: Blockierenden Prozess beenden
# Prozess-ID ermitteln
lsof -i :8080
# Prozess beenden
kill -9 <PID>
Option 3: Konfliktierenden Container stoppen
docker stop <conflicting_container>
Hinweis: Bei --network=host nutzt der Container das Host-Netzwerk direkt – Portkonflikte sind häufiger. Container-Ports dürfen dann nicht mit Host-Ports kollidieren.
Szenario 4: Unzureichende Berechtigungen
Typische Anzeichen:
- Exit Code 1
- Logs mit
Permission denied,Operation not permitted,chown: changing ownership failed
Praxisbeispiel:
MongoDB-Container mit gemountetem Datenverzeichnis auf dem Host:
chown: changing ownership of '/data/db': Permission denied
Das Host-Verzeichnis gehörte root; MongoDB im Container lief als User mongodb (UID 999) ohne Schreibrechte.
Troubleshooting:
Host-Verzeichnisberechtigungen:
ls -la /host/data/path
User im Container:
docker run -it my-app /bin/bash
whoami
id
SELinux prüfen (CentOS/RHEL):
getenforce
Lösungen:
Option 1: Host-Verzeichnisberechtigungen anpassen
# Alle Rechte (unsicher, nur Entwicklung)
chmod 777 /host/data/path
# Sicherer: Owner anpassen
chown -R 999:999 /host/data/path # 999 = UID im Container
Option 2: Privileged Mode (vorsichtig)
docker run --privileged=true my-app
Gibt dem Container fast alle Host-Rechte – Sicherheitsrisiko, in Produktion nicht empfohlen.
Option 3: User explizit setzen
docker run --user 1000:1000 my-app # UID/GID vom Host
Option 4: SELinux
# Option 1: Z-Label (Host-Dateilabel anpassen)
docker run -v /host/path:/container/path:Z my-app
# Option 2: z-Label (geteiltes Label)
docker run -v /host/path:/container/path:z my-app
# Option 3: SELinux temporär deaktivieren (Produktion nicht empfohlen)
setenforce 0
Szenario 5: Abhängiger Dienst nicht bereit
Typische Anzeichen:
- Exit Code 1
- Logs mit DB-Verbindungsfehlern, Redis-Timeout
Connection refused,ECONNREFUSED,could not connect to server
Praxisbeispiel:
Microservices per docker-compose – App-Container hängt von MySQL ab. Beide starten fast gleichzeitig, App schlägt fehl:
Error: connect ECONNREFUSED 172.18.0.2:3306
MySQL-Container lief, aber der Dienst initialisierte noch – die App startete zu früh, Verbindung fehlgeschlagen, Exit.
Troubleshooting:
Abhängige Dienste prüfen:
docker ps # laufen die benötigten Container?
Netzwerk testen:
docker exec my-app ping database
docker exec my-app telnet database 3306
docker exec my-app nc -zv database 3306
Docker-Netzwerk:
docker network ls
docker network inspect <network_name>
Lösungen:
Option 1: Healthcheck und depends_on in docker-compose
version: '3.8'
services:
database:
image: mysql:8.0
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
app:
image: my-app
depends_on:
database:
condition: service_healthy # warten bis DB healthy
Option 2: Retry-Logik in der Anwendung
// Node.js-Beispiel
async function connectWithRetry(maxRetries = 5) {
for (let i = 0; i < maxRetries; i++) {
try {
await db.connect();
console.log('Database connected');
return;
} catch (err) {
console.log(`Connection failed, retrying... (${i+1}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
throw new Error('Failed to connect to database');
}
Option 3: Warte-Skript vor dem Start
Z. B. wait-for-it.sh im Dockerfile:
# Im Dockerfile
COPY wait-for-it.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/wait-for-it.sh
# Beim Start
CMD ["wait-for-it.sh", "database:3306", "--", "node", "app.js"]
Option 4: Restart-Policy
docker run --restart=on-failure:3 my-app # max. 3 Neustarts
In docker-compose:
services:
app:
restart: on-failure
Kombinierbar: Healthcheck + Retry in der App + Restart-Policy.
Präventive Maßnahmen und Best Practices
Bisher ging es um Reparatur nach dem Fehler. Mit der richtigen Konfiguration von Anfang an vermeiden oder überstehen viele Probleme automatisch.
Healthcheck (HEALTHCHECK) konfigurieren
Healthchecks prüfen regelmäßig, ob der Container wirklich funktioniert – nicht nur, ob der Prozess noch läuft.
Im Dockerfile:
FROM nginx:alpine
# Alle 30 s prüfen, Timeout 3 s, 3 Fehlschläge = unhealthy
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD curl -f http://localhost/ || exit 1
Web-Service – HTTP-Endpunkt:
HEALTHCHECK --interval=30s --timeout=5s --start-period=40s \
CMD curl -f http://localhost:8080/health || exit 1
Datenbank – spezifische Befehle:
# MySQL
HEALTHCHECK CMD mysqladmin ping -h localhost || exit 1
# PostgreSQL
HEALTHCHECK CMD pg_isready -U postgres || exit 1
# Redis
HEALTHCHECK CMD redis-cli ping || exit 1
Vorteile:
- Kubernetes/Swarm starten oder verschieben Container basierend auf Health-Status
- docker-compose depends_on wartet auf echte Bereitschaft
- Monitoring kann auf Health-Status alarmieren
Health-Status anzeigen:
docker ps # STATUS-Spalte zeigt health
docker inspect --format='{{.State.Health.Status}}' <container_id>
Restart-Policy setzen
Restart-Policies ermöglichen automatische Wiederherstellung – ohne nächtlichen manuellen Eingriff.
Vier Strategien:
no (Standard): Kein automatischer Neustart
docker run --restart=no my-app
Für Einmal-Jobs.
on-failure[:max-retries]: Nur bei abnormaler Beendigung
docker run --restart=on-failure:5 my-app # max. 5 Versuche
Nur bei Exit-Code ≠ 0.
always: Immer neu starten
docker run --restart=always my-app
Für dauerhaft laufende Dienste. Startet auch nach Docker-Daemon-Neustart – auch nach manuellem docker stop.
unless-stopped: Immer neu starten, außer manuell gestoppt
docker run --restart=unless-stopped my-app
Wie always, aber nach manuellem docker stop kein Auto-Start beim Daemon-Neustart. Meine bevorzugte Strategie.
Wichtig:
- 10-Sekunden-Regel: Restart-Policy greift erst, wenn der Container mindestens 10 Sekunden lief – Schutz vor Endlosschleifen bei Konfigurationsfehlern.
- Endlos-Restart-Falle: Bei Portkonflikt o. Ä. wachsen Logs explosionsartig – Log-Rotation mitdenken.
Policy für laufende Container ändern:
docker update --restart=unless-stopped <container_id>
In docker-compose:
services:
web:
image: nginx
restart: unless-stopped # Produktion empfohlen
worker:
image: my-worker
restart: on-failure
Log-Management: Speicherplatz schonen
Docker speichert Container-Logs standardmäßig als JSON-Dateien – über Monate können das Dutzende GB werden. Ich habe Produktionsserver erlebt, die wegen voller Docker-Logs ausfielen.
Log-Rotation (empfohlen):
/etc/docker/daemon.json anlegen oder bearbeiten:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
Docker neu starten:
sudo systemctl restart docker
Pro Container maximal ca. 30 MB Logs (10 MB × 3), alte Dateien werden gelöscht.
Pro Container:
docker run --log-opt max-size=10m --log-opt max-file=3 my-app
In docker-compose:
services:
app:
image: my-app
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Weitere Treiber:
- syslog: System-Log
- journald: systemd journal
- fluentd: zentralisierte Log-Verwaltung
- none: keine Logs (nicht empfohlen)
Log-Pfad und Größe:
docker inspect --format='{{.LogPath}}' <container_id>
du -h $(docker inspect --format='{{.LogPath}}' <container_id>)
Monitoring und Alarme: Probleme früh erkennen
Nicht erst reagieren, wenn Container bereits down sind – Monitoring verhindert viele Incidents.
Basis: docker stats
docker stats # alle Container in Echtzeit
docker stats <container_id> # einzelner Container
CPU, Speicher, Netzwerk- und Disk-I/O. Steigt Speicher dauerhaft, mögliches Leck – früh handeln.
Produktion: Prometheus + Grafana
# docker-compose.yml
services:
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana
ports:
- "3000:3000"
cadvisor: # Container-Metriken
image: google/cadvisor
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
ports:
- "8080:8080"
Alarmregeln für Speicher > 80 %, häufige Neustarts usw.
Einfach: Cron-Skript
#!/bin/bash
# check-containers.sh
EXITED=$(docker ps -a -f "status=exited" --format "{{.Names}}")
if [ -n "$EXITED" ]; then
echo "Warning: The following containers are exited:"
echo "$EXITED"
# E-Mail oder Push-Benachrichtigung
fi
Crontab alle 5 Minuten:
*/5 * * * * /path/to/check-containers.sh
Checkliste für Produktionsumgebungen
Referenz-Konfiguration für stabile Container:
version: '3.8'
services:
web:
image: my-web-app:latest
# Restart-Policy
restart: unless-stopped
# Ressourcenlimits
deploy:
resources:
limits:
cpus: '2'
memory: 1G
reservations:
memory: 512M
# Healthcheck
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 40s
# Log-Management
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# Umgebungsvariablen (Secrets für sensible Daten)
environment:
- NODE_ENV=production
# Port-Mapping
ports:
- "8080:8080"
# Abhängigkeiten
depends_on:
database:
condition: service_healthy
database:
image: postgres:14
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
volumes:
- db-data:/var/lib/postgresql/data
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
volumes:
db-data:
Mit dieser Konfiguration: automatischer Neustart, Ressourcenlimits, kontrollierte Logs, Monitoring – deutlich ruhiger schlafen.
Fazit
Docker-Container-Startfehler sind kein Grund zur Panik – fehlende Systematik schon.
Kernpunkte:
Exit-Codes verstehen: 137 → Speicher; 1 → Konfiguration oder Abhängigkeiten. Exit-Codes sind Hinweise von Docker.
Vier-Schritte-Methode:
- Container-Status (
docker ps -a) - Logs (
docker logs) - Konfiguration (
docker inspect) - Interaktive Verifikation (
docker run -it)
Über 90 % der Fälle lösen sich in Schritt 2.
Fünf typische Szenarien: Konfigurationsfehler, Speichermangel, Portkonflikt, Berechtigungen, Abhängigkeiten nicht bereit.
Prävention: Healthchecks, Restart-Policy, Log-Rotation, Monitoring – Stabilität und automatische Erholung.
Schnell-Checkliste zum Speichern:
Docker-Container-Startfehler – Checkliste
□ Schritt 1: docker ps -a – Status und Exit-Code
□ Schritt 2: docker logs <container_id> – detaillierte Logs
□ Schritt 3: docker inspect <container_id> – Konfiguration
□ Schritt 4: docker run -it <image> – interaktive Verifikation
Schnelle Zuordnung:
- Exit Code 1 + „No such file" → Mount-Pfade und Konfiguration
- Exit Code 1 + „port already allocated" → Portkonflikt
- Exit Code 1 + „Permission denied" → Berechtigungen und SELinux
- Exit Code 1 + „Connection refused" → Abhängige Dienste
- Exit Code 137 + OOMKilled=true → Speicherlimit erhöhen
- Exit Code 127 → CMD/ENTRYPOINT-Pfad prüfen
Prävention:
□ HEALTHCHECK konfigurieren
□ restart-Policy (empfohlen: unless-stopped)
□ Log-Rotation (max-size + max-file)
□ Ressourcenlimits (-m Speicher)
□ Monitoring (docker stats oder Prometheus)
Wenn dieser Artikel geholfen hat: bookmarken und beim nächsten Container-Problem parat halten. Besondere Fälle gerne in den Kommentaren teilen – vielleicht hilft es anderen.
Mögen Ihre Container dauerhaft Up and Running bleiben – und Sie keinen Freitagabend-Alarm mehr wegen abgestürzter Container bekommen!
Vollständiger Troubleshooting-Workflow bei fehlgeschlagenen Docker-Container-Starts
Systematische Fehlerbehebung mit Erklärung der Exit-Codes 137/1, Vier-Schritte-Methode und Lösungen für fünf typische Fehlerszenarien
⏱️ Estimated time: 30 min
- 1
Step 1: Exit-Codes und Schweregrad des Problems verstehen
Bedeutung der Exit-Codes:
• Exit Code 0: Normaler Exit, Aufgabe abgeschlossen
• Exit Code 1: Anwendungsfehler, Startbefehl fehlgeschlagen (am häufigsten)
• Exit Code 137: OOM Killer, Speichermangel
• Exit Code 127: Befehl nicht gefunden
• Exit Code 139: Segmentation Fault (C/C++-Programme)
Schweregrad:
• In der Produktion waren alle Container der vier Kernservices im Exited-Status
• Container beenden sich sofort nach dem Start – systematische Fehlerbehebung erforderlich
Schnelle Zuordnung:
• Exit Code 1 + No such file → Mount-Pfade und Konfigurationsdateien prüfen
• Exit Code 1 + port already allocated → Portkonflikt prüfen
• Exit Code 1 + Permission denied → Dateiberechtigungen und SELinux prüfen
• Exit Code 1 + Connection refused → Prüfen, ob abhängige Dienste bereit sind
• Exit Code 137 + OOMKilled=true → Speicherlimit erhöhen - 2
Step 2: Vier-Schritte-Methode
Vier-Schritte-Methode:
Schritt 1: Container-Status und Exit-Code prüfen
• docker ps -a – Status und Exit-Code anzeigen
• Spalten State und Exit Code beachten
Schritt 2: Detaillierte Logs prüfen
• docker logs <container_id> – vollständige Logs
• docker logs --tail 50 <container_id> – letzte 50 Zeilen
• docker logs -f <container_id> – Logs in Echtzeit verfolgen
Schritt 3: Konfiguration prüfen
• docker inspect <container_id> – Konfiguration anzeigen
• Felder Cmd, Entrypoint, Env usw. prüfen
Schritt 4: Interaktive Verifikation
• docker run -it <image> – interaktiv testen
• Startbefehl manuell ausführen und Fehlermeldungen beobachten - 3
Step 3: Fünf typische Fehlerszenarien und Lösungen
Fünf typische Fehlerszenarien:
Szenario 1: Falscher Startbefehl
• CMD/ENTRYPOINT falsch konfiguriert
• Lösung: Startbefehl korrigieren, Pfade und Parameter prüfen
Szenario 2: Fehlerhafte Konfigurationsdatei
• Falscher Pfad, falsches Format
• Lösung: Konfigurationsdatei korrigieren, Pfade und Format validieren
Szenario 3: Abhängiger Dienst nicht bereit
• Datenbank nicht gestartet
• Lösung: Auf Bereitschaft warten (depends_on + healthcheck)
Szenario 4: Speichermangel
• OOM Killer beendet Prozess
• Lösung: Speicherlimit erhöhen (--memory) oder Speichernutzung optimieren
Szenario 5: Portkonflikt
• Port bereits belegt
• Lösung: Port-Mapping ändern (-p 8081:80) oder blockierenden Prozess beenden
Best Practices:
• Healthchecks in docker-compose konfigurieren
• depends_on + healthcheck für abhängige Dienste
• Angemessene Ressourcenlimits setzen (Speicher, CPU)
FAQ
Warum beendet sich ein Docker-Container sofort nach dem Start?
Bedeutung der Exit-Codes:
• Exit Code 1: Anwendungsfehler, Startbefehl fehlgeschlagen (am häufigsten)
• Exit Code 137: OOM Killer, Speichermangel
• Exit Code 0: Normaler Exit, Aufgabe abgeschlossen
Schnelle Zuordnung:
• Exit Code 1 + No such file → Mount-Pfade und Konfigurationsdateien prüfen
• Exit Code 1 + port already allocated → Portkonflikt prüfen
• Exit Code 1 + Permission denied → Dateiberechtigungen und SELinux prüfen
• Exit Code 1 + Connection refused → Prüfen, ob abhängige Dienste bereit sind
• Exit Code 137 + OOMKilled=true → Speicherlimit erhöhen
Troubleshooting: Vier-Schritte-Methode (Logs prüfen → Exit-Code prüfen → Startbefehl prüfen → Ressourcenlimits prüfen)
Wie behebt man fehlgeschlagene Docker-Container-Starts?
1) Container-Logs prüfen: docker logs container-name
2) Exit-Code prüfen: docker ps -a
3) Startbefehl prüfen: docker inspect container-name
4) Ressourcenlimits prüfen: docker stats
Detaillierte Schritte:
• Schritt 1: docker ps -a – Status und Exit-Code anzeigen
• Schritt 2: docker logs <container_id> – detaillierte Logs
• Schritt 3: docker inspect <container_id> – Konfiguration prüfen
• Schritt 4: docker run -it <image> – interaktive Verifikation
Was ist der Unterschied zwischen Exit Code 1 und Exit Code 137?
• Exit Code 1: Anwendungsfehler, Startbefehl fehlgeschlagen
• Exit Code 137: OOM Killer, Speichermangel
• Exit Code 0: Normaler Exit
• Andere Exit-Codes: je nach Anwendung
Häufige Ursachen für Exit Code 1:
• Falscher Startbefehl (CMD/ENTRYPOINT falsch konfiguriert)
• Fehlerhafte Konfigurationsdatei (falscher Pfad, falsches Format)
• Abhängiger Dienst nicht bereit (Datenbank nicht gestartet)
• Portkonflikt (Port bereits belegt)
Häufige Ursachen für Exit Code 137:
• Speichermangel (OOM Killer)
• Speicherlimit erhöhen (--memory)
Wie löst man typische Probleme bei fehlgeschlagenen Container-Starts?
1) Falscher Startbefehl (CMD/ENTRYPOINT falsch konfiguriert)
2) Fehlerhafte Konfigurationsdatei (falscher Pfad, falsches Format)
3) Abhängiger Dienst nicht bereit (Datenbank nicht gestartet)
4) Speichermangel (OOM Killer)
5) Portkonflikt (Port bereits belegt)
Lösungen:
• Startbefehl korrigieren
• Konfigurationsdatei korrigieren
• Auf Bereitschaft abhängiger Dienste warten (depends_on + healthcheck)
• Speicherlimit erhöhen (--memory)
• Port-Mapping ändern (-p 8081:80)
• Healthchecks in docker-compose konfigurieren
14 Min. Lesezeit · Veröffentlicht am: 18. Dez. 2025 · Aktualisiert am: 14. Juli 2026
Docker Praxisleitfaden
Wenn du über die Suche hier gelandet bist, kommst du am schnellsten weiter, indem du zum vorherigen oder nächsten Beitrag dieser Serie springst.
Vorheriger
Docker-Container-Debugging: exec nutzen – die richtige Art, Container-Probleme zu finden
Ausführliche Anleitung zu docker exec zum Debuggen in Containern: Unterschiede zu attach, Tool-Installation, Benutzerrechte und praktische Beispiele für schnelles Troubleshooting.
Teil 36 von 38
Nächster
Self-Hosted Dev Sandboxes mit Docker und Go: Preview-URLs ohne Kubernetes
Ein Praxisleitfaden für selbst gehostete Dev Sandboxes mit Docker, Go und Traefik: Preview-URLs, Ressourcenlimits, Docker-Socket-Grenzen und Betrieb.
Teil 38 von 38
Ähnliche Beiträge
Docker vs. virtuelle Maschine: Performance-Unterschiede und Szenario-Auswahl in 5 Minuten

Docker vs. virtuelle Maschine: Performance-Unterschiede und Szenario-Auswahl in 5 Minuten
Docker-Installation ohne Fallstricke (2025): Vollständige Lösungen von permission denied bis zum erfolgreichen Start


Kommentare
Melde dich mit GitHub an, um einen Kommentar zu hinterlassen