Docker-Container vs. VM: Wann welcher Virtualisierungstyp das Richtige ist
Die häufigste Frage in Homelab-Forums und bei BsN-Beratungsgesprächen klingt so: „Soll ich das in Docker oder in einer VM machen?" Die Frage beruht auf einem grundlegenden Irrtum: Container und VMs seien austauschbare Begriffe für dasselbe Prinzip. Sie sind es nicht.
Ein Container teilt sich den Kernel des Host-Systems und virtualisiert nur die Userspace-Umgebung – Bibliotheken, Dateisystem, Prozessisolation. Eine Virtuelle Maschine virtualisiert die gesamte Hardware, inklusive eigenem Kernel und eigenem Betriebssystem. Das ist der wichtigste Unterschied, und er bestimmt fast alle nachfolgenden Praktikabilitätsfragen.
Vergleichstabelle
| Kriterium | Docker-Container | Virtuelle Maschine |
|---|---|---|
| Isolation | Prozess- und Dateisystemebene; selber Kernel wie Host | Vollständige Hardware-Isolation; eigener Kernel; gegenseitige Beeinflussung praktisch unmöglich |
| Speicherbedarf (Idle) | Einige Megabyte (Basis-Image); oft < 100 MB pro Container | 1–4 GB je VM (OS-Image, zugewiesener RAM, Swap) |
| Startzeit | Sekunden (Prozessstart) | Minuten (OS-Boot, Services starten) |
| Backup | docker commit / Volume-Snapshots / Compose-Dateien als Code | VM-Image-Snapshot (z.B. Proxmox qm backup, vzdump) oder ganze Platte |
| GUI-Programme | Nur indirekt (X11/VDI-Forwarding möglich, aber umständlich) | Direkt, vollständiges grafisches OS |
| Hardware-Durchreichen | Möglich für GPU (--gpus), USB (linuxserver/letsencrypt bypass) und Netzwerk, aber Host-Kernel-abhängig | Einfacher: PCI/USB/Netzwerk passthrough in Hypervisor config (Proxmox: qm set --hostpci0, usb0) |
| Sicherheitsrisiko | Kernel-Shared = Kernel-Exploit betrifft alle Container; kein eigener Kernel-Schutz | Geringeres Risiko; Kernel-Isolierung; bei gehackter VM bleibt Host normalerweise unberührt |
Entscheidungshilfe: Die Regelform
In einen Container gehört …
1. Dienste ohne GUI, die nur TCP/HTTP/Liste socken – Webserver, Datenbanken, Messaging (PostgreSQL, Redis, MQTT, Nextcloud, Vaultwarden). Beispiel: docker run -d -p 80:80 nginx.
2. Stateless- oder leicht stateful-Dienste, deren Daten auf Volumes ausgelagert sind: docker compose mit volumes: Block und einem definierten docker-entrypoint.sh. Das Backup-Szenario ist dann meist ein Volume-Snapshot oder ein docker cp.
3. Apps, die einen spezifischen Linux-Kernel nicht brauchen – also Python/Node/Java-Apps, die auf einem aktuellen Debian- oder Alpine-Kernel laufen würden, gleich wie der Host.
4. Skalierbare, replizierbare Dienste, bei denen man ohnehin mehrere Instanzen starten will: Docker Compose oder Kubernetes-ähnliche Orchestrierung ist der natürliche Rahmen.
Konkretes Signal: Wenn du eine Dockerfile schreiben kannst, die nur Pakete installiert, einen Binärstart ausführt und Ports expose – der Dienst gehört fast immer in einen Container.
Auf eine VM gehört …
1. Anwendungen, die ein eigenes, festes Betriebssystem voraussetzen – Windows-Server, ältere Linux-Versionen mit anderem Kernel als dem Host, BSD.
2. Dienste, die Hardware-Durchreichen in der Hypervisor-Sprache voraussetzen – z.B. eine VM mit direkt zugewiesenem GPU-PCI, einer IDE/SATA-Platte oder einem USB-Schnittstellen-Gerät, das der Host-Kernel nicht selbst behandeln soll. In Proxmox: qm set <VMID> --hostpci0 <PCI-Addr> oder USB-Add: qm set <VMID> --usb0 host=....
3. Sicherheitskritische, isolierte Dienste, bei denen ein gemeinsamer Kernel ein unakzeptables Risiko ist – z.B. ein öffentlich zugängener Dienst auf einem Multi-Tenant-Host, oder Testumgebungen für Kernel-Exploits.
4. Anwendungen, die Bare-Metal-nahe Performance für I/O brauchen und deren Container-Laufzeitumgebung zu viel Overhead oder zu viele Kernel-Abhängigkeiten einführt.
Konkretes Signal: Wenn du ein ISO-Image mounten, einen eigenen Kernel booten oder Geräte von der VM aus mit eigenen Treibern initialisieren willst – das ist eine VM.
Auf den Bare Metal (Host ohne Container, ohne VM) gehört …
- Das Hypervisor-Betriebssystem selbst – Proxmox VE ist ein eigenständiges Debian-basiertes OS; andere Hypervisor-OSe (ESXi, XCP-ng) ebenso.
- Proxmox VE Web GUI, daemon-gesteuerte Dienste der Host-Infrastruktur – z.B.
pvedaemon,pveproxy,corosync,lvm2für Storage-Pools, Networking auf dem Host. - Dienste, die den Host-Kernel direkt beeinflussen müssen – Kernel-Module (z.B.
vfio-pcifür GPU-Passthrough),iptables/nftables-Regeln auf dem physischen Interface, oder LVM/RAID-Konfiguration. - Dockershim-Passthrough auf Fremd-Hypervisorn – manche Orchestrierungen verlangen, dass Docker direkt auf der VM läuft, die ihrerseits eine VM ist (Doppelvirtualisierung); das gehört auf die innere VM, nicht auf den Host.
Sonderfälle, bei denen die Regeln nicht greifen
GPU-Container
Ein Container, der eine GPU benötigt (Machine-Learning, transcodes, Rendering), ist eigentlich ein Container – aber mit Hardware-Passthrough: docker run --gpus all ... (NVidia Runtime) oder --device /dev/dri/renderD128 für VA-API. Das funktioniert nur, wenn der Host-Kernel die GPU als Device bereitstellt und kein Kernel-Modul (wie vfio-pci) sie bereits für eine VM eingesogen hat. Bei einer FC-Passthrough (Full Container) mit GPU und einem gleichzeitigen GPU-Passthrough für eine VM entsteht ein Konflikt: GPU kann nur einem Gast zur Zeit zugeordnet sein. Entscheidungshilfe: ML-Inference im Container (kürzere Laufzeiten), dedizierte GPU-Workloads (Training) eher VM, wenn auch andere Hardware-Isolierungen nötig sind.
USB-Durchreichen an Container
Manche Container wollen physische USB-Geräte (Zwingend z.B. für bestimmte Praxissysteme): docker run --device /dev/bus/usb/001/002 .... Das setzt voraus, dass der Host-Kernel das Gerät wie gewünscht sieht und dass udev-Regeln auf dem Host keine Konflikte verursachen. Bei komplexen USB-Geräten, die eigene Kernel-Treiber brauchen, ist eine VM mit USB-Passthrough (qm set --usb0 host=...) oft zuverlässiger.
Windows-Dienste
Windows-Dienste laufen in Docker-Containern nur eingeschränkt (Windows-Container etabliert, aber meist Windows-Server-Hosts nötig, selten im Homelab). Die Praxisentscheidung: Eine Windows-Dienst-App gehört in eine Windows-VM. Docker-Container mit Wine sind eine Grauzone und für produktive Dienste nicht empfehlenswert.
Docker-Desktop-Anwendungen auf einem Windows-PC
Docker Desktop auf Windows nutzt eine eingebettete Hyper-V-VM (WSL2 oder hyperv daemons). Du hast dort drei Schichten: Windows-Host → Docker Desktop VM (Hyper-V/WSL2) → Container. Bei Problemen mit Volume-Mounts oder Netzwerk: oft liegt es an der VM-Schicht, nicht am Container. Ein Port, der von außen nicht erreichbar ist, ist häufig ein WSL2-NAT-Problem (Windows-Subnetz 172.16.0.0/12, forwarding aus WSL2 heraus muss explizit gestattet sein).
LXC und Docker: Verwirrend ähnlich, aber unterschiedliche Garantien
Proxmox VE bringt LXC (Linux Containers) nativ mit. LXC ist ein Container-ähnliches System, das auf dem selben physikalischen Kernel läuft wie Docker (beide nutzen Linux Namespaces und cgroups). Wo sie sich unterscheiden:
- LXC ist ein systembezogener Container: Er bootet ein vollständiges Userspace-Linux (init, systemd oder OpenRC) und sieht von innen fast wie eine minimale VM aus (
tty,/dev, Paketmanager). Backup überpct backupodervzdump(ganzes Container-Rootfs-Archiv). Wahl zwischen Privilegierten und unprivilegierten Containern (mapped UIDs/GIDs bei unprivilegiert). - Docker ist ein App-Container: Ein Prozess pro Container, ein vorhersagbares Lebenszyklus (start → run → stop), keine systemweiten Dienste im Container.
Die Sicherheitsgarantie ist unterschiedlich: Ein privilegierter LXC-Container (pct unprivileged 0) teilt sich mehr Kernel-Fähigkeiten als ein Standard-Docker-Container. Ein unprivilegierter LXC-Container plus User-Namespaces ist ähnlich sicher wie Docker mit Rootless-Modus. Für reine Diensteroberflächen im Homelab sind LXC und Docker oft austauschbar; bei Bedarf an einem eigenen init-Prozess oder einem Init-System im Container ist LXC natürlicher.
Kurz: LXC ist das Werkzeug, wenn du einen ganzen (minimalen) Linux-Dienst im Container haben willst; Docker ist das Werkzeug, wenn du eine einzelne Anwendung mit definiertem Lebenszyklus willst.
FAQ
F1: Kann ich nicht einfach alles in Docker legen, um Ressourcen zu sparen?
Nein, nicht wenn der Dienst ein eigenes Kernel-Verhalten oder gerätespezifische Initialisierung braucht. Ein VM-basierter Dienst mit eigenem Kernel und eigenem Treiber-Einsatz ist nicht durch einen Container ersetzbar, ohne die Anforderungen zu verlieren. Ressourcensparnis ist ein Argument, nicht das einzige Argument.
F2: Ist Proxmox mit LXC und Docker gleichzeitig sinnvoll?
Ja. Typisches Setup: Proxmox-Host (Bare Metal) → VM für Windows oder GUI-Dienste → innerhalb einer Linux-VM (oder direkt auf dem Proxmox-Host-LXC-Container) Docker für die Diensteebene. Oder: LXC für leichte System-Container, Docker für die Anwendungs-Container auf demselben Host. Mix und Match nach den Regeln oben.
F3: Was ist das Sicherheitsrisiko, wenn ein Container gehackt wird?
Das Ausmaß hängt vom Container-Typ und von den Kernel-Fähigkeiten ab. Ein root-fähiger Docker-Container mit --privileged hat effektiv root auf dem Host – bei einem Kernel-Exploit ist der ganze Host betroffen. Ein unprivilegierter Container ohne Devices und ohne --privileged begrenzt die Schadensfläche, aber ein Kernel-Exploit im Container kann theoretisch den Host kompromittieren, weil beide denselben Kernel nutzen. Eine VM mit eigener Kernel-Isolierung begrenzt den Schaden auf die VM.
F4: Welches Backup soll ich wählen – Volume oder VM-Snapshot?
Container-Backup = Volumes kopieren (docker volume inspect zeigt den Pfad; dann rsync oder Snapshot des Host-Dateisystems) plus Compose-Konfigurationsdatei als Code sichern. VM-Backup = ganze VM-Snapshot/Backup (qm backup <VMID> <backup-storage>). Wenn du beides nutzt, sind die VM-Backups oft einfacher zu verwenden und wiederherzustellen (einheitlicher Mechanismus); Container-Backups sind im Detail genauer (nur die Daten, nicht das gesamte OS-Image). Praxis: beide parallel, je nach Wichtigkeit.
Hinweis: Konrad Konfigurationsdetails (PCI-Adressen, USB-IDs, prompte Pfade) sind jeweils systemabhängig; Beispiele zeigen Syntax. Dokumentation für Treiber und Geräte: lspci -nn, lsusb, docker volume inspect, pct config auf dem Proxmox-Host.
Hinweis: Dieser Artikel ist redaktioneller Inhalt und enthält keine Affiliate- oder Partner-Links. Alle Angaben entsprechen dem Stand 2026 und können sich ändern.