Docker Container sind keine schlanken VMs: vier Fragen, eine Antwort
15.11.2026
Thema: alle Beiträge zu Docker
Ein Docker Container ist ein Linux-Prozess, keine kleine VM. Vier Fragen zu Docker und Kubernetes, die sich daraus herleiten lassen, jede nachgemessen.
Inhaltsverzeichnis
- Ein Docker Container ist ein Prozess
- Warum ein Docker Container in Millisekunden startet
- Warum Docker unter Windows und macOS eine Linux-VM braucht
- Warum ein Docker Container schwächer isoliert als eine VM
- Warum Kubernetes ohne dockerd auskommt
- Fazit
Ein Docker Container ist ein Prozess
„Docker Container sind doch nur schlanke VMs.” Der Satz klingt plausibel und ist technisch falsch. Eine virtuelle Maschine emuliert einen kompletten Rechner, mit Hypervisor und eigenem Gast-Kernel. Ein Docker Container hat nichts davon. Er ist ein ganz normaler Linux-Prozess, dem der Kernel weniger zeigt (Namespaces), weniger gibt (cgroups) und ein eigenes Wurzeldateisystem unterschiebt (das Image).
Wie diese drei Bausteine funktionieren und welche Kette hinter dem Kommando docker run arbeitet, steht in Docker Architektur: ein Container ist nur ein Prozess. Hier geht es um den Nutzen dieses einen Satzes. Wer ihn ernst nimmt, muss vier Dinge nicht mehr auswendig lernen, die sonst wie Docker-Folklore wirken: Er kann sie sich herleiten, und jede Herleitung lässt sich in einer Minute am eigenen Rechner nachmessen.
Gemessen habe ich mit der Docker Engine 29.7.2 unter Windows, direkt in WSL 2, ohne Docker Desktop. Deine Zahlen und PIDs werden andere sein, die Aussagen dahinter nicht.
Warum ein Docker Container in Millisekunden startet
Die Herleitung: Wenn ein Docker Container ein Prozess ist, bootet beim Start nichts. Keine Firmware, kein Kernel, kein Init-System. Der Kernel läuft schon, er startet nur einen weiteren Prozess.
Die Messung: ein Container, der nichts tut, außer sich sofort wieder zu beenden.
time docker run --rm alpine true
Fünf Läufe lagen zwischen 455 und 533 Millisekunden. Das ist die gesamte Strecke: REST-Aufruf an den Daemon, Namespaces und cgroup anlegen, Dateisystem einhängen, Netzwerk verdrahten, Prozess starten, auf sein Ende warten, alles wieder abbauen. Wie viel davon Verwaltung ist, zeigt derselbe Lauf ohne Netzwerk:
time docker run --rm --network none alpine true
Jetzt sind es 324 bis 360 Millisekunden. Rund ein Drittel der Zeit ging also allein dafür drauf, dem Container ein virtuelles Netzwerk-Interface zu bauen und es wieder abzureißen. Auch der Rest ist Buchhaltung und kein Bootvorgang, denn es gibt nichts, das hochfahren müsste.
Warum Docker unter Windows und macOS eine Linux-VM braucht
Die Herleitung: Ein Linux-Prozess braucht einen Linux-Kernel. Ein Image bringt Dateien mit, aber keinen Kernel. Also muss unter Windows und macOS irgendwo ein Linux laufen.
Die Messung: dieselbe Frage an den Host und an zwei Container mit verschiedenen Distributionen.
uname -r
docker run --rm alpine uname -r
docker run --rm debian:13-slim uname -r
6.18.58.1-microsoft-standard-WSL2
6.18.58.1-microsoft-standard-WSL2
6.18.58.1-microsoft-standard-WSL2
Dreimal derselbe Kernel. Alpine und Debian unterscheiden sich nur in den Dateien, die ihr Image mitbringt:
docker run --rm alpine grep PRETTY_NAME /etc/os-release
docker run --rm debian:13-slim grep PRETTY_NAME /etc/os-release
PRETTY_NAME="Alpine Linux v3.24"
PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
Der Name des Kernels verrät den Rest: microsoft-standard-WSL2. Auf meinem Windows-Rechner kommt der Linux-Kernel aus WSL 2, und WSL 2 ist selbst eine schlanke virtuelle Maschine. Docker Desktop macht unter Windows und macOS dasselbe: Es startet im Hintergrund eine kleine Linux-VM, und in der laufen die Container. Die VM ist also nicht der Container. Sie ist der Ort, an dem der Kernel wohnt, den sich alle Container teilen.
Warum ein Docker Container schwächer isoliert als eine VM
Die Herleitung: Alle Container teilen sich den Kernel des Hosts, das hat die letzte Messung gezeigt. Zwischen zwei VMs steht ein Hypervisor. Zwischen zwei Containern steht nur die Sichtblende, die ein und derselbe Kernel aufstellt.
Die Messung: ein Container, der fünf Minuten schläft, und dann der Blick vom Host.
docker run -d --name herleitung --memory 64m alpine sleep 300
docker inspect -f '{{.State.Pid}}' herleitung
15964
Das ist die PID des Containers auf dem Host. Mit ihr lässt sich der Prozess ganz normal anschauen:
ps -o user,pid,ppid,comm -p 15964
USER PID PPID COMMAND
root 15964 15939 sleep
Der Prozess steht in der Prozessliste des Hosts, und er läuft dort als root. Von innen sieht derselbe Prozess anders aus:
docker exec herleitung ps
PID USER TIME COMMAND
1 root 0:00 sleep 300
8 root 0:00 ps
Außen PID 15964, innen PID 1: derselbe Prozess, zwei Sichten. Auch der Ressourcen-Deckel ist nichts weiter als eine Zahl in einer Datei des Kernels:
docker exec herleitung cat /sys/fs/cgroup/memory.max
67108864
Das sind genau die 64 MiB aus dem Startkommando.
Root im Container ist in der Standardkonfiguration derselbe Benutzer wie root auf dem Host. Was ihn zurückhält, sind Namespaces, ein reduzierter Satz an Capabilities und ein Seccomp-Filter, aber kein zweiter Kernel. Deshalb ist eine Kernel-Lücke im Container eine Kernel-Lücke auf dem Host. Und deshalb sind die Option --privileged oder ein hineingereichter Docker-Socket so gefährlich: Sie nehmen genau diese Sichtblende wieder weg. Wie schnell daraus in Kubernetes eine Root-Shell auf dem Node wird, zeigt Ein Pod, und der Server gehört ihm.
Warum Kubernetes ohne dockerd auskommt
Die Herleitung: Wenn am Ende der Kette nur ein Prozess steht, den runc startet und containerd verwaltet, dann wird dockerd für den laufenden Container gar nicht gebraucht.
Die Messung: der Elternprozess des Containers von eben, die PPID 15939 aus der Ausgabe oben.
ps -o user,pid,ppid,comm -p 15939
USER PID PPID COMMAND
root 15939 1 containerd-shim
Der Elternprozess heißt containerd-shim-runc-v2, ps kürzt den Namen. Dessen Elternprozess ist die PID 1, also systemd. dockerd taucht in dieser Ahnenreihe nicht auf. Er läuft daneben als eigener Dienst, genau wie containerd selbst.
dockerd ist für den Container also Auftraggeber, nicht Elternteil, und einen Auftraggeber kann man austauschen. Genau das tut Kubernetes: Der Kubelet spricht über die CRI-Schnittstelle direkt mit containerd oder einer anderen Runtime wie CRI-O. Den eingebauten Docker-Adapter dockershim gibt es seit Kubernetes 1.24 nicht mehr. Deine Images laufen trotzdem weiter, weil Image-Format und Runtime als OCI-Standards offen spezifiziert sind. Welche Runtime dein Cluster benutzt, steht in der Spalte CONTAINER-RUNTIME von kubectl get nodes -o wide.
Zum Schluss aufräumen:
docker rm -f herleitung
Fazit
- Ein Docker Container ist ein Linux-Prozess, dem der Kernel weniger zeigt und weniger gibt. Vier Dinge folgen daraus von selbst.
- Er startet schnell, weil nichts bootet: rund eine halbe Sekunde für Anlegen, Starten und Aufräumen, davon etwa ein Drittel für das Netzwerk.
- Er braucht einen Linux-Kernel und bringt keinen mit. Unter Windows und macOS wohnt dieser Kernel in einer VM.
- Er isoliert schwächer als eine VM, weil sich alle Container einen Kernel teilen. Root im Container ist root auf dem Host, nur mit Sichtblende.
- Er hängt nicht an dockerd. Sein Elternprozess ist der containerd-shim, und deshalb kommt Kubernetes ohne Docker aus.
Das ist die erste Säule einer Plattform, die dir gehört: verstehen, was da läuft, statt Kommandos auswendig zu lernen. Die zweite steckt in denselben Messungen. Namespaces und cgroups gehören zum Linux-Kernel, runc und containerd sind offene Projekte unter dem Dach von Linux Foundation und CNCF, Image-Format und Runtime sind OCI-Standards. Docker Desktop ist ein Produkt mit eigener Lizenz. Der Container darunter gehört keinem Hersteller.
Mit genau diesem Gedanken beginnt meine Docker- und Kubernetes-Schulung, noch bevor Docker überhaupt installiert ist.
© 2026 Trutz Software Consulting GmbH. CC BY 4.0: Dieser Text darf mit Namensnennung weiterverwendet und bearbeitet werden, auch kommerziell. Code-Beispiele darin stehen unter Apache 2.0. Ausgenommen sind Marke und Logo sowie gekennzeichnete Zitate Dritter. Was das genau heißt.
Newsletter
Erhalte praxisnahe Tutorials, Best Practices und echte Lösungen für die häufigsten DevOps-Probleme direkt in Dein Postfach.
Datenschutz: Deine E-Mail-Adresse wird DSGVO-konform in Deutschland gespeichert. Keine Spam, nur relevante Inhalte. Eine E-Mail alle 1 bis 2 Wochen.