Container-Shell ohne Bash betreten - Debugging in minimalen Images
Container-Shell ohne Bash betreten - Debugging in minimalen Images
Minimale Images haben keine Bash, Distroless-Images haben gar keine Shell — hier sind die Techniken um trotzdem in einen Container zu kommen.
Alpine: sh statt bash
Alpine-basierte Images (die Mehrheit der Docker Hub Images) haben kein bash, nur sh:
# Schlägt fehl:
docker exec -it container bash
# Funktioniert:
docker exec -it container sh
# Oder explizit:
docker exec -it container /bin/sh
Tools wie curl, dig, ss sind in Alpine nicht vorinstalliert. Temporär installieren:
docker exec -it container sh
apk add --no-cache curl bind-tools
Distroless: Keine Shell vorhanden
Google Distroless-Images (gcr.io/distroless/...) enthalten nur das Minimum — keine Shell, kein Package Manager, keine Unix-Utilities. docker exec liefert nur:
OCI runtime exec failed: exec failed: unable to start container process:
exec: "sh": executable file not found in PATH
Lösung 1: Debug-Tag des Images
Viele Distroless-Images haben eine Debug-Variante mit BusyBox-Shell:
# Normales Image:
FROM gcr.io/distroless/python3
# Debug-Variante (für lokale Entwicklung):
docker run -it gcr.io/distroless/python3:debug sh
Lösung 2: Ephemeral Debug-Container
Ein temporärer Container teilt Netzwerk, PID-Namespace und Volumes mit dem Ziel-Container:
docker run --rm -it \
--pid=container:ZIELCONTAINER \
--network=container:ZIELCONTAINER \
--volumes-from ZIELCONTAINER \
busybox sh
- Jetzt kann man:
- Prozesse des Ziel-Containers sehen (
ps aux) - Das Netzwerk des Containers nutzen (
wget,curl) - Auf die Dateisysteme des Containers zugreifen
Lösung 3: nsenter (Host-Zugriff)
Auf dem Host in den Namespaces des Containers eintreten:
# PID des Container-Hauptprozesses herausfinden
docker inspect CONTAINER --format '{{.State.Pid}}'
# In Container-Namespaces eintreten (braucht root)
sudo nsenter -t PID -m -u -i -n -p sh
nsenter gibt Zugriff ohne Shell im Container — direkter Zugriff über den Host-Kernel.
Nützliche Debug-Images
# netshoot — vollständiges Netzwerk-Debug-Toolkit
docker run --rm -it --network container:ZIELCONTAINER nicolaka/netshoot
# busybox — minimale Shell + Unix-Tools
docker run --rm -it --network container:ZIELCONTAINER busybox sh
# alpine — apk Package Manager verfügbar
docker run --rm -it --network container:ZIELCONTAINER alpine sh
Debugging-Tools kurz hinzufügen
# Temporär curl in laufenden Container installieren (Alpine)
docker exec container apk add --no-cache curl
# Prüfen, dann wieder entfernen
docker exec container curl http://otherservice:3000
docker exec container apk del curl
Wichtig: Diese Änderungen sind flüchtig — beim nächsten Container-Start sind sie weg. Für dauerhafte Tools: ins Dockerfile aufnehmen.
strace für low-level Debugging
# strace im Container nutzen (Container muss --cap-add=SYS_PTRACE haben)
docker run --cap-add=SYS_PTRACE --rm -it ubuntu strace ls
# Oder in laufendem Container
docker exec container strace -p PID
Zusammenfassung
| Image-Typ | Methode |
|-----------|---------|
| Alpine | docker exec container sh |
| Debian/Ubuntu | docker exec container bash |
| Distroless | Debug-Tag oder ephemeral Container |
| Distroless auf Host | nsenter |
Ephemeral Debug-Container sind die universellste Lösung — sie hinterlassen keine Spuren und funktionieren bei jedem Image-Typ.
Weiterführend
Bash-Skripting, Shell-Grundlagen und Debugging-Techniken unter Linux sind auf nolr.nexon.cyou ausführlich behandelt.