Docker-Container-Debugging: exec nutzen – die richtige Art, Container-Probleme zu finden

Die API in der Testumgebung liefert plötzlich 502. docker ps zeigt den Container als „Up 2 hours“ – er scheint zu laufen. In den Logs steht nur ein knappes „Connection refused“.
In solchen Momenten ist das frustrierend: Der Container läuft, aber Sie wissen nicht, was drinnen passiert. Stimmt die Konfiguration? Laufen die Prozesse? Hört der Dienst auf dem Port? Dafür müssen Sie „hinein“ – wie in eine Blackbox schauen.
Als ich Docker neu war, wusste ich nicht, wie man einen Container „betritt“. Mal hieß es docker exec, mal docker attach, mal einfach neu starten. Nach einigen Fehlern wurde klar: Container-Debugging hat eine saubere Vorgehensweise.
Dieser Artikel zeigt, wie Sie mit docker exec Container-Probleme richtig untersuchen: Unterschied zu attach, fehlende Tools und praktische Tricks. Damit müssen Sie beim nächsten Vorfall nicht nur noch zum Neustart greifen.
docker exec – Grundlagen: richtig in den Container
Der einfachste Weg
Um einen laufenden Container zu betreten, reicht meist:
docker exec -it my-nginx bash
Drei Teile sind wichtig:
-it: Kombination aus-i(STDIN offen) und-t(Terminal) – für interaktive „Konversation“ mit dem Containermy-nginx: Containername oder ID (z. B.docker exec -it abc123def456 bash)bash: der Befehl im Container – hier eine Bash-Shell
Danach sieht die Eingabezeile etwa so aus: root@abc123def456:/# – Sie sind im Container und können wie auf einem Linux-Server arbeiten.
Wenn bash fehlt
Manchmal erscheint:
$ docker exec -it my-alpine bash
OCI runtime exec failed: exec failed: container_linux.go:380:
starting container process caused: exec: "bash": executable file not found
Kein Drama: Alpine und andere Minimal-Images bringen oft nur sh mit:
docker exec -it my-alpine sh
Praxis: zuerst bash, sonst sh – das deckt die meisten Fälle ab.
Container-ID statt Name
# Container-ID anzeigen
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
abc123def456 nginx "/docker-entrypoint.…" 2 hours ago
# Mit ID-Präfix (3–4 Zeichen reichen oft)
$ docker exec -it abc1 bash
Docker matcht eindeutige Präfixe – praktisch bei vielen Containern.
Container wieder verlassen
Mit exit oder Strg+D:
root@abc123def456:/# exit
exit
$
Wichtig: Nach exec stoppt der Container nicht. Darum gleich der Unterschied zu attach.
exec vs. attach – nicht verwechseln
Der Wesensunterschied
Viele Tutorials nennen exec und attach, erklären den Unterschied selten. Mit attach habe ich einmal einen Container ungewollt gestoppt.
Kurz:
- docker exec: startet einen neuen Prozess im Container – wie ein zusätzliches Fenster
- docker attach: verbindet den Hauptprozess (PID 1) – wie „Spiegeln“ des laufenden Prozesses
Beispiel: docker attach my-nginx, dann Strg+C oder exit – der Hauptprozess (Nginx) bekommt ein Exit-Signal, der Container stoppt. In Produktion riskant.
Mit docker exec -it my-nginx bash läuft eine separate Bash; deren Ende betrifft Nginx nicht.
Wann exec, wann attach?
In fast allen Fällen: exec.
attach nur, wenn Sie wirklich mit dem Hauptprozess interagieren müssen, z. B.:
- interaktives Programm im Vordergrund (Python-REPL)
- Live-Ausgabe des Hauptprozesses
- mehrere Terminals sehen dieselbe tty-Ausgabe
Für Dateien prüfen, Konfiguration lesen oder Befehle ausführen: exec.
Vergleich auf einen Blick
| Eigenschaft | docker exec | docker attach |
|---|---|---|
| Neuer Prozess | ✓ ja | ✗ nein |
| Container stoppt nach exit | ✗ nein | ✓ ja (riskant) |
| Beliebige Befehle | ✓ ja | ✗ nein |
| Unabhängige Terminals | ✓ ja | ✗ nein (gemeinsame tty) |
| Für Debugging | ⭐⭐⭐⭐⭐ | ⭐ |
attach ist eher für Ausgabe gedacht, nicht für tägliches Debugging.
Fehlende Tools im Container
Warum so wenig Befehle?
Drinnen wollen Sie vim nutzen:
root@abc123:/# vim /etc/nginx/nginx.conf
bash: vim: command not found
Oder curl:
root@abc123:/# curl localhost:8080
bash: curl: command not found
Sogar ping fehlt oft. Das ist Absicht: Images bleiben klein – nur Nötiges, kein vim/curl/ping. Ubuntu kann hunderte MB haben, Alpine nur wenige.
Tools temporär installieren
Je nach Basis-Image:
Debian/Ubuntu (apt/apt-get):
apt-get update
apt-get install -y vim curl wget net-tools
apt-get install -y iputils-ping dnsutils
CentOS/RedHat (yum):
yum install -y vim curl wget
Alpine (apk):
apk update
apk add vim curl bash
Welches System läuft?
cat /etc/os-release
which apt-get # Debian/Ubuntu
which yum # CentOS/RHEL
which apk # Alpine
Oft: apt-get update probieren, bei Fehler wechseln – unkritisch.
Ist das unkritisch?
Entwicklung: temporär installieren ist üblich; nach Neustart ist der Zustand weg.
Produktion: nur bei akutem Troubleshooting; danach Tools ins Dockerfile und Image neu bauen.
Gründe:
- Sicherheit: ad-hoc-Pakete können Schwachstellen einführen
- Reproduzierbarkeit: nach Restart fehlt alles wieder
Langfristig: Dockerfile
FROM nginx:latest
RUN apt-get update && apt-get install -y \
vim \
curl \
wget \
net-tools \
iputils-ping \
&& rm -rf /var/lib/apt/lists/*
# weitere Konfiguration...
rm -rf /var/lib/apt/lists/* hält das Image schlank.
Praktischer Tipp ohne vim
Oft reichen cat oder less:
cat /etc/nginx/nginx.conf
less /etc/nginx/nginx.conf # q zum Beenden
head -n 20 /etc/nginx/nginx.conf
Änderungen notfalls mit sed:
sed -i 's/listen 80/listen 8080/g' /etc/nginx/nginx.conf
Mit bestimmtem Benutzer in den Container
Warum Benutzer angeben?
root@abc123:/app# cat /var/log/app.log
cat: /var/log/app.log: Permission denied
root@abc123:/app# chmod 644 config.yaml
chmod: changing permissions of 'config.yaml': Operation not permitted
Trotz root@ in der Prompt: Der Container kann als Nicht-Root laufen (empfohlen in Produktion). exec übernimmt oft die Container-User-Einstellung.
Als root
docker exec -it --user root my-app bash
# oder
docker exec -it -u root my-app bash
Bestimmte UID
docker exec -it --user 1000 my-app bash
docker exec -it --user appuser my-app bash
docker exec -it --user 1000:1000 my-app bash
Hilfreich bei Schreibrechten:
docker exec -it --user appuser my-app bash
appuser@abc123:/app$ touch /data/test.txt
touch: cannot touch '/data/test.txt': Permission denied
# Rechteproblem bestätigt
Wann root nötig ist
Typisch für:
- Systemkonfiguration unter
/etc/ - Paketinstallation (apt, yum)
- Logs unter
/var/log/ chmod/chown- Netzwerk-Tools wie tcpdump, netstat (oft root)
Wenn möglich ohne root – besonders in Produktion.
Sicherheit
Test: flexibler.
Produktion:
- reinschauen → ok
- kurzfristige Config-Änderung → dokumentieren
- Software im laufenden Container bauen/installieren → ins Dockerfile auslagern
Container sind immutable: Laufzeit-Änderungen verschwinden beim Restart. Dauerhafte Änderungen gehören ins Image.
Hinweis: Container-root kann je nach Setup UID 0 mit dem Host teilen – deshalb Nicht-Root-User in Produktion.
Praxis: Befehle und typische Szenarien
Einzelbefehl ohne interaktive Shell
Ohne -it:
docker exec my-nginx ls -la /etc/nginx/
docker exec my-nginx cat /etc/nginx/nginx.conf
docker exec my-nginx ps aux
docker exec my-nginx netstat -tlnp
docker exec my-nginx curl -I localhost:80
Für Skripte und Health-Checks:
if docker exec my-app curl -f http://localhost:8080/health; then
echo "App is healthy"
else
echo "App is down!"
fi
Standard-Debug-Ablauf
1. Status
docker ps -a
2. Logs
docker logs my-app --tail 100
docker logs my-app -f
3. Prozesse
docker exec my-app ps aux
4. Ports
docker exec my-app netstat -tlnp
docker exec my-app ss -tlnp
5. Erreichbarkeit
docker exec my-app curl localhost:8080
docker exec my-app telnet localhost 8080
6. Konfiguration
docker exec my-app cat /etc/nginx/nginx.conf
docker exec my-app cat /app/config.yaml
7. Speicher
docker exec my-app df -h
Nützliche Kombinationen
docker exec my-app env | grep DATABASE
docker exec my-app find /app -name "*.log"
docker exec my-app ls -la /app/
docker stats my-app
Mehrere Container:
for container in $(docker ps -q); do
echo "Container: $container"
docker exec $container free -h
echo "---"
done
Netzwerk
docker exec containerA ping containerB
docker exec my-app ping -c 3 google.com
docker exec my-app nslookup google.com
docker inspect my-app | grep IPAddress
docker exec my-app ip addr show
Container startet sofort neu
Methode 1: Startbefehl überschreiben
docker run -it --name debug-app my-app-image sh
Methode 2: gestoppten Container
docker start my-app
docker logs my-app
docker exec -it my-app bash
Fazit
Kernpunkte:
docker exec ist der sichere Weg – Beenden stoppt den Container nicht. Merksatz: docker exec -it <name> bash, sonst sh.
exec ≠ attach – attach am Hauptprozess, exit kann den Container beenden. Standard: exec.
Fehlende Tools: apt/yum/apk für Notfälle; dauerhaft ins Dockerfile.
Root: --user root bei Bedarf; in Produktion dokumentieren und ins Image übernehmen.
Reihenfolge: Logs → Prozesse → Konfiguration → Netzwerk.
Checkliste:
- Läuft der Container? (
docker ps) - Fehler in Logs? (
docker logs) - Prozesse aktiv? (
docker exec … ps aux) - Ports offen? (
docker exec … netstat -tlnp) - Konfiguration korrekt? (
docker exec … cat …) - Genug Speicher? (
docker exec … df -h) - Netzwerk ok? (
docker exec … curl/ping)
Damit finden Sie die meisten Ursachen – oft Config, Rechte oder Portkonflikte – ohne blind neu zu starten.
Vollständiger Docker-Container-Debug-Ablauf
Schritt-für-Schritt-Troubleshooting mit exec: Befehle, Tool-Installation, Rechteverwaltung und systematische Checks
⏱️ Estimated time: 30 min
- 1
Step 1: In den Container: exec vs. attach verstehen
Wesentlicher Unterschied: exec startet einen neuen Prozess im Container (empfohlen, Hauptprozess bleibt unberührt), attach verbindet stdin/stdout des Hauptprozesses (nicht empfohlen – Beenden stoppt den Container).
Grundbefehle:
• docker exec -it container-name /bin/bash (Bash-Shell)
• docker exec -it container-name sh (sh, häufig bei Alpine)
• docker exec container-name command (einzelner Befehl ohne interaktive Shell)
Parameter:
• -i: STDIN offen halten (interaktiv)
• -t: Pseudo-Terminal zuweisen (formatierte Ausgabe)
• -it zusammen für beste Ergebnisse
Anwendung: exec für Debugging, Tool-Installation und Konfiguration; attach nur für Live-Log-Ausgabe. - 2
Step 2: Fehlende Tools und Berechtigungsprobleme lösen
Tool-Installation:
• Debian/Ubuntu: apt-get update && apt-get install -y tool-name
• Alpine: apk add --no-cache tool-name
• CentOS/RHEL: yum install -y tool-name
Nur-Lese-Dateisystem: zuerst ausführbar machen:
docker exec -u root container-name sh -c 'mount -o remount,rw /'
Benutzerrechte:
• -u root für Root-Rechte: docker exec -u root container-name
• --user uid:gid für bestimmten Benutzer
• Aktueller Benutzer: whoami
• Dateirechte: ls -la
• Rechte ändern: chmod 755 file, chown user:group file
Hinweis: Root in Produktion sparsam nutzen; Änderungen dokumentieren und ins Dockerfile übernehmen – nach Neustart sind Container-Änderungen weg. - 3
Step 3: Systematischer Debug-Check
Checkliste (in dieser Reihenfolge):
1) Logs: docker logs container-name oder /var/log im Container
2) Prozesse: ps aux | grep process-name
3) Ports: netstat -tuln | grep port oder ss -tuln
4) Konfiguration: cat /path/to/config
5) Speicher: df -h
6) Netzwerk: curl http://localhost:port, ping hostname
Ablauf: Logs für Fehlermeldungen → Prozesse für laufende Dienste → Konfiguration ausschließen → Netzwerk prüfen.
So lösen Sie die überwiegende Mehrheit typischer Container-Probleme.
FAQ
Warum exec statt attach zum Betreten des Containers?
• exec: neuer Prozess im Container, Hauptprozess unberührt, Container läuft nach dem Beenden weiter
• attach: Verbindung zu stdin/stdout des Hauptprozesses, Beenden stoppt den Container
daher eignet sich exec für sicheres Debugging; attach vor allem für Live-Logs.
Was tun, wenn weder bash noch sh im Container vorhanden ist?
• Andere Shell: docker exec -it container-name /bin/ash (Alpine)
• Einzelbefehl: docker exec container-name command (ohne interaktive Shell)
• Verfügbare Shells: docker exec container-name ls /bin/
• busybox: docker exec -it container-name busybox sh
Für regelmäßiges interaktives Debugging bash oder sh im Dockerfile vorinstallieren.
Wie installiere ich Tools in einem Container mit nur-Lese-Dateisystem?
1. Remount:
docker exec -u root container-name sh -c 'mount -o remount,rw /'
2. Dann installieren:
docker exec -u root container-name apt-get update
docker exec -u root container-name apt-get install -y tool-name
Nach Neustart sind Änderungen weg – Schritte ins Dockerfile oder Multi-Stage-Build übernehmen.
Container kann externes Netzwerk nicht erreichen – was prüfen?
1. Netzwerkmodus:
docker inspect container-name | grep NetworkMode
2. DNS:
docker exec container-name nslookup google.com
3. Erreichbarkeit:
docker exec container-name ping -c 3 8.8.8.8
4. Firewall:
docker exec container-name iptables -L
5. Custom Network:
docker network inspect network-name
Häufige Ursachen: DNS, Firewall, falscher Netzwerkmodus.
Wie beende ich exec, ohne den Container zu stoppen?
• exit oder Strg+D: normaler Ausstieg, Container läuft weiter
• Strg+P, dann Strg+Q: Detach ohne Stop
• Terminal schließen: bei -it meist unkritisch
Nicht attach nutzen und Strg+C drücken – das stoppt den Hauptprozess. Nach exec bleibt der Container unverändert aktiv.
7 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-Log-Management in der Praxis: Von Treiber-Konfiguration bis zentraler Sammlung
Ausführliche Analyse der Docker-Log-Treiber, Log-Rotation und zentraler Sammlung – mit Best Practices und Fallstricken für Produktionsumgebungen
Teil 35 von 38
Nächster
Docker-Container startet und beendet sich sofort? Vollständige Troubleshooting-Anleitung (inkl. Exit-Codes 137/1)
Startet Ihr Docker-Container sofort und wechselt in den Exited-Status? Dieser Artikel bietet eine systematische Fehlerbehebung, erklärt Exit-Codes 137 und 1, eine Vier-Schritte-Methode und Lösungen für fünf typische Fehlerszenarien – für schnelle Diagnose und Behebung.
Teil 37 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