Docker auf einem LXC-vServer: was geht und was nicht
Unsere vServer nutzen LXC-Containervirtualisierung. Anders als bei einer vollwertigen KVM-Maschine teilen sich alle Container den Kernel des Host-Systems. Für Docker ist das grundsätzlich kein Hindernis, denn Docker-Container sind selbst nur Prozesse mit abgeschottetem Namensraum - keine echten virtuellen Maschinen.
Damit Docker innerhalb eines LXC-Containers laufen kann, muss allerdings Nesting aktiviert sein. Das ist bei unseren vServern der Fall, du musst dafür nichts beantragen oder umstellen.
Funktioniert
- Docker Engine und Docker Compose
- Images aus Docker Hub und eigenen Registries
- Eigene Images bauen per Dockerfile
- Volumes, Netzwerke, Port-Mapping
- Automatischer Neustart per restart-Policy
Funktioniert nicht
- Verschachtelte Virtualisierung, also eigene VMs per KVM innerhalb des Containers
- Container, die eigene Kernel-Module nachladen wollen
- Images, die zwingend einen Windows-Kernel brauchen
Für die allermeisten Anwendungsfälle - Webanwendungen, Datenbanken, Reverse Proxies, Bots, Automatisierung - ist das völlig ausreichend. Mehr zum Unterschied findest du im Ratgeber LXC oder KVM.
Voraussetzungen
Bevor du loslegst, sollte der vServer aktuell und grundlegend abgesichert sein. Falls noch nicht geschehen, arbeite zuerst die ersten Schritte und die SSH-Absicherung ab.
Zur Tarifwahl: Docker selbst verbraucht kaum Ressourcen, die Container darin sehr wohl. Als Anhaltspunkt:
- Tarif S: ein bis zwei kleine Container, etwa ein Bot oder ein statischer Webserver.
- Tarif M: ein typischer Stack aus Reverse Proxy, Anwendung und Datenbank.
- Tarif L oder XL: mehrere Stacks parallel, Entwicklungsumgebungen oder speicherhungrige Anwendungen wie Nextcloud mit Volltextsuche.
Nicht unterschätzen solltest du den Speicherplatz: Docker-Images belegen schnell mehrere Gigabyte, alte Layer bleiben ohne Aufräumen liegen.
Docker Engine installieren
Die Version aus den Standard-Paketquellen von Debian und Ubuntu ist meist veraltet. Nimm deshalb die offiziellen Docker-Paketquellen. Zuerst die Vorbereitung:
sudo apt update
sudo apt install ca-certificates curl gnupg -y
sudo install -m 0755 -d /etc/apt/keyrings
Dann den Signaturschlüssel holen. Für Debian:
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Für Ubuntu ersetzt du in beiden Zeilen debian durch ubuntu. Anschließend installierst du:
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
Der Test:
sudo docker run --rm hello-world
Erscheint die Begrüßungsmeldung, läuft Docker. Der Parameter --rm räumt den Testcontainer gleich wieder ab.
Docker ohne sudo benutzen
Damit du nicht bei jedem Befehl sudo voranstellen musst, nimmst du deinen Benutzer in die Gruppe docker auf:
sudo usermod -aG docker $USER
Die Änderung greift erst nach einer neuen Anmeldung - melde dich also ab und wieder an. Danach funktioniert docker ps ohne sudo.
Sei dir dabei bewusst: Mitglieder der Gruppe docker können über Container faktisch Root-Rechte auf dem gesamten System erlangen. Nimm nur Benutzer auf, denen du diese Rechte ohnehin geben würdest.
Erster Compose-Stack
Einzelne docker run-Befehle sind für Tests praktisch, im Dauerbetrieb aber unhandlich. Docker Compose beschreibt stattdessen den gesamten Stack in einer Datei, die du versionieren und wiederverwenden kannst.
Lege ein Verzeichnis an und darin eine compose.yaml:
mkdir -p ~/stacks/demo && cd ~/stacks/demo
nano compose.yaml
Ein minimales Beispiel mit Webserver und Datenbank:
services:
web:
image: nginx:alpine
restart: unless-stopped
ports:
- "127.0.0.1:8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
db:
image: mariadb:11
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: bitte-hier-ein-langes-zufallspasswort
MARIADB_DATABASE: demo
volumes:
- dbdata:/var/lib/mysql
volumes:
dbdata:
Starten, Status prüfen, Logs ansehen:
docker compose up -d
docker compose ps
docker compose logs -f web
Zwei Details in dieser Datei sind wichtiger, als sie aussehen. restart: unless-stopped sorgt dafür, dass die Container nach einem Neustart des Servers von allein wieder hochkommen. Und die Portangabe 127.0.0.1:8080:80 bindet den Dienst bewusst nur an localhost - dazu gleich mehr.
Ports, Firewall und ein bekannter Fallstrick
Hier stolpern viele: Docker umgeht deine ufw-Regeln. Schreibst du in der Compose-Datei ports: - "8080:80", trägt Docker eigene iptables-Regeln ein, die vor denen von ufw greifen. Der Dienst ist dann aus dem Internet erreichbar, obwohl ufw status den Port gar nicht listet. Das ist kein Fehler, sondern eine bewusste Design-Entscheidung von Docker - sie überrascht nur regelmäßig.
Der saubere Umgang damit sieht so aus:
- Nur an localhost binden: Schreibe
"127.0.0.1:8080:80"statt"8080:80". Der Container ist dann nur vom Server selbst aus erreichbar. - Einen Reverse Proxy davorsetzen: nginx oder Caddy lauschen auf 80 und 443, terminieren TLS und reichen intern an die Container weiter. Nur diese beiden Ports gibst du in der Firewall frei.
- Interne Kommunikation über das Compose-Netzwerk: Container im selben Stack erreichen sich über ihren Servicenamen, im Beispiel oben also per
dbals Hostname. Dafür brauchst du überhaupt kein Port-Mapping.
Wie du den Reverse Proxy samt kostenlosem SSL-Zertifikat aufsetzt, steht im Ratgeber Webserver einrichten.
Speicherplatz im Griff behalten
Docker sammelt: alte Images, verwaiste Volumes, Build-Caches. Auf einem vServer mit begrenztem NVMe-Speicher merkst du das schneller als auf einer großen Maschine. Verschaffe dir regelmäßig einen Überblick:
docker system df
Aufräumen lässt sich in zwei Stufen. Die harmlose Variante entfernt gestoppte Container, ungenutzte Netzwerke und verwaiste Images:
docker system prune
Die gründliche Variante nimmt zusätzlich ungenutzte Volumes mit - und damit potenziell Datenbankinhalte:
docker system prune -a --volumes
Den zweiten Befehl nur ausführen, wenn du sicher weißt, welche Volumes gerade nicht in Benutzung sind. Ein Backup vorher schadet nie.
Updates und Betrieb
Container aktualisierst du, indem du das Image neu ziehst und den Stack neu startest:
cd ~/stacks/demo
docker compose pull
docker compose up -d
Compose ersetzt dabei nur die Container, deren Image sich tatsächlich geändert hat. Daten in benannten Volumes bleiben erhalten.
Zwei Gewohnheiten, die sich im Dauerbetrieb auszahlen: Verwende feste Versions-Tags statt latest, damit ein pull nicht ungewollt einen Major-Sprung mitbringt. Und sichere deine Compose-Dateien zusammen mit den Volume-Inhalten - eine compose.yaml allein bringt dir bei einem Datenverlust wenig.
Häufige Fragen
vServer für deinen Docker-Stack
Ein einzelner kleiner Container läuft bereits auf dem Tarif S. Für einen typischen Stack aus Reverse Proxy, Anwendung und Datenbank ist M die sinnvolle Einstiegsgröße. Alle Tarife mit NVMe-SSD, unlimitiertem Traffic und vollem Root-Zugriff.
vServer-Tarife & Preise ansehen