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.