Zum Hauptinhalt springen

UNABHÄNGIGES WISSENSFORUM Unabhängige Hosting-Community • Keine offizielle Verbindung zur netcup GmbH.

NETCUP GUIDE
FORUM · GUTSCHEINPOOL
Tutorials Stufe: Einsteiger Dauer: 20 Min. // 18 Min. Lesezeit • Geprüft:

Docker Engine auf einem Netcup VPS oder Root-Server installieren (inkl. Fix für den UFW-Firewall-Bypass)

Da jeder Netcup VPS und Root-Server auf echter QEMU/KVM-Hardwarevirtualisierung statt auf einem geteilten LXC/OpenVZ-Kernel basiert, läuft die Docker Engine mit nativer Geschwindigkeit und ohne jegliche cgroupv2- oder overlay2-Einschränkungen. Wer jedoch einfach apt install docker.io ausführt, erhält veraltete Distributionspakete, unbegrenzt wachsende JSON-Container-Logs, die früher oder später Ihre SSD/NVMe füllen, und eine gefährliche Sicherheitslücke, bei der Docker stillschweigend Ihre UFW-Firewall-Regeln umgeht. Diese Anleitung installiert die offizielle Upstream-Docker-CE-Suite und härtet sowohl das Daemon-Logging als auch das Netzwerk-Port-Binding ab.

THREAD-AUTOR // OP Marcus Vance Lead Cloud Infrastructure Architect (EU KVM & Netzwerk-Engineering)
MOD-PRÜFUNG // CO-MAINTAINER Elena Rostova Senior Linux Systems & Security Auditor
BEITRAGSSTATUS // AKTUALISIERT Community-Standards →
MODERATOR-HINWEIS // TESTUMGEBUNG & TRANSPARENZ Verifiziert mit offiziellen Docker CE (docker-ce v27+) Paketen, dem overlay2-Storage-Treiber auf ext4/XFS sowie den Netcup SCP Edge-Firewall-Regeln.

VORAUSSETZUNGEN // ANFORDERUNGEN

CHECKLISTE
  • ✓ Ein Netcup VPS (z. B. VPS 500 G12.5 mit 4 GB ECC-RAM oder VPS 1000 G12.5 mit 8 GB ECC-RAM) oder Root-Server (RS 1000 G12.5) mit Ubuntu 24.04 LTS oder Debian 12
  • ✓ Ein eingerichteter sudo-Benutzer ohne Root-Direktlogin per SSH

Wichtige Erkenntnisse (Key Takeaways)

KURZFAZIT
  • 01 Installieren Sie docker-ce, docker-ce-cli, containerd.io und docker-compose-plugin immer aus dem offiziellen, kryptografisch signierten APT-Repository von Docker statt über das veraltete Ubuntu-Paket docker.io oder Snap.
  • 02 Konfigurieren Sie /etc/docker/daemon.json mit max-size: "10m", max-file: "3" und live-restore: true, damit Container-Logs niemals Ihre Festplatte füllen und Container während eines Docker-Daemon-Upgrades weiterlaufen.
  • 03 Kritische Sicherheitsregel: Das Veröffentlichen eines Ports mit -p 5432:5432 schreibt Regeln in die PREROUTING/DOCKER-Netfilter-Ketten VOR UFW – und legt Ihre Datenbank weltweit offen! Binden Sie interne Ports immer explizit an 127.0.0.1:5432:5432 und aktivieren Sie die Netcup SCP Edge-Firewall.
📑 Inhaltsverzeichnis (3 Abschnitte) ▼
§ 01

Schritt 1: Veraltete Pakete entfernen & offizielles Docker-GPG-Repository einbinden

Entfernen Sie zunächst eventuell vorhandene Container-Pakete der Distribution (docker.io, podman-docker, containerd) und stellen Sie sicher, dass kein docker-Snap-Paket installiert ist. Die in den Standard-Repositories von Ubuntu und Debian gepflegten docker.io-Pakete hinken den offiziellen Upstream-Releases oft um mehrere Monate hinterher, teilen Buildx und Compose v2 in abweichende Paketnamen auf und erhalten wichtige runc- oder containerd-Sicherheitsfixes teilweise verzögert.

Noch problematischer auf produktiven KVM-Servern ist das Ubuntu-snap-Paket für Docker: Da Snap den Docker-Daemon in einer eigenen AppArmor- und Mount-Namespace-Sandbox kapselt, kommt es regelmäßig zu Berechtigungsfehlern beim Einbinden von Bind-Mounts außerhalb von /home, zu verzögerten Daemon-Starts beim Booten sowie zu unerwünschten automatischen Neustarts laufender Datenbank-Container während eines Snap-Auto-Refreshs. Für produktive Server auf Netcup ist das offizielle APT-Repository von Docker (download.docker.com) daher der einzig empfehlenswerte Standard.

Wir legen den öffentlichen GPG-Schlüssel von Docker im Verzeichnis /etc/apt/keyrings/docker.asc ab und verknüpfen ihn über das Attribut signed-by=/etc/apt/keyrings/docker.asc direkt in der /etc/apt/sources.list.d/docker.list. Im Gegensatz zum veralteten Befehl apt-key add, der Schlüssel global für sämtliche Paketquellen des Systems freigab, vertraut apt diesem Schlüssel ausschließlich für Pakete aus dem offiziellen Docker-Repository.

Durch das Auslesen von /etc/os-release ($ID und $VERSION_CODENAME) erkennt das folgende Installationsskript vollautomatisch, ob Ihr Netcup-Server unter Ubuntu 24.04 LTS (noble) oder Debian 12 (bookworm) läuft, und installiert docker-ce, docker-ce-cli, containerd.io, docker-buildx-plugin sowie docker-compose-plugin (Compose v2 als natives Go-Plugin docker compose).

Offizielles Docker CE APT-Repository einrichten & Docker Engine + Compose v2 installieren
bash
# 1. Eventuell vorhandene Distributionspakete sauber entfernen
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do
  sudo apt-get remove -y $pkg 2>/dev/null || true
done

# 2. Voraussetzungen installieren und offiziellen GPG-Schlüssel von Docker hinterlegen
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
. /etc/os-release
sudo curl -fsSL "https://download.docker.com/linux/${ID}/gpg" -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# 3. Offizielles Docker APT-Repository einbinden
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/${ID} ${VERSION_CODENAME} stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 4. Docker Engine, CLI, containerd, Buildx und Compose v2 installieren
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
docker --version && docker compose version

Befehlserklärung: Erkennt über /etc/os-release automatisch, ob Ihr Netcup-Server unter ubuntu oder debian läuft, bindet die signierte APT-Paketquelle ein und installiert die aktuelle Docker Engine inklusive Buildx und Compose v2.

ERWARTETE AUSGABE
Docker version 27.3.1, build ce12230
Docker Compose version v2.29.7
§ 02

Schritt 2: /etc/docker/daemon.json härten (Log-Rotation, Live-Restore & IPAM-Pools)

Standardmäßig speichert Dockers json-file-Logging-Treiber jede Zeile auf stdout/stderr unbegrenzt auf der Festplatte. Auf einem produktiven Nginx-, Traefik- oder Node.js-Container auf einem Netcup VPS 1000 G12.5 oder RS 1000 G12.5 können unrotierte Container-Logs unter /var/lib/docker/containers/<id>/<id>-json.log im Laufe weniger Monate unbemerkt 40 GB bis 80 GB NVMe-Speicher verschlingen – bis PostgreSQL oder MariaDB plötzlich mit ENOSPC (No space left on device) abstürzt. Mit "max-size": "10m" und "max-file": "3" begrenzen wir das Log-Volumen jedes einzelnen Containers strikt auf maximal 30 MB.

Ebenso wichtig für hohe Verfügbarkeit ist "live-restore": true. In der Standardeinstellung beendet der dockerd-Daemon beim Stoppen oder Neustarten alle laufenden Container-Prozesse. Wenn unattended-upgrades ein Sicherheitsupdate für docker-ce einspielt, führt das ohne Live-Restore jedes Mal zu einem kurzen Ausfall Ihrer gesamten Web- und Datenbank-Stacks. Ist "live-restore": true gesetzt, bleiben die Container unter der Kontrolle von containerd-shim unterbrechungsfrei aktiv, während der Management-Daemon dockerd im Hintergrund neu startet.

Zusätzlich setzen wir "userland-proxy": false. Standardmäßig startet Docker für jeden veröffentlichten Port einen eigenen Userspace-Prozess namens docker-proxy, der Pakete zwischen Host- und Container-Socket im Arbeitsspeicher hin- und herkopiert. Wird dieser deaktiviert, übernimmt der Linux-Kernel die Weiterleitung vollständig über native Netfilter/iptables-NAT-Regeln (inklusive Hairpin-NAT), was den RAM-Verbrauch senkt und zusätzliche Kontextwechsel zwischen Kernel- und Userspace vermeidet.

Schließlich definieren wir über "default-address-pools" eindeutige /24-Bridge-Subnetze aus dem Bereich 172.20.0.0/14. Ohne diese Vorgabe vergibt Docker Compose für jedes neue Projekt ein komplettes /16-Netz (172.18.0.0/16, 172.19.0.0/16 usw.), sodass bereits nach rund 30 Compose-Netzwerken der private Adressraum erschöpft ist oder es zu Routing-Konflikten mit internen WireGuard-, Tailscale- oder OpenVPN-Tunneln kommt. Mit /24-Blöcken (je 254 Container-IPs pro Projekt) stehen Ihnen über 1.000 konfliktfreie Docker-Netzwerke zur Verfügung.

Produktionsreife /etc/docker/daemon.json schreiben & Docker neu starten
bash
cat << 'EOF' | sudo tee /etc/docker/daemon.json
{
  "storage-driver": "overlay2",
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3",
    "compress": "true"
  },
  "live-restore": true,
  "userland-proxy": false,
  "default-address-pools": [
    {
      "base": "172.20.0.0/14",
      "size": 24
    }
  ]
}
EOF

# systemd neu laden und Docker-Daemon mit den neuen Einstellungen starten
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo docker info | grep -E "Storage Driver|Logging Driver|Live Restore"

Befehlserklärung: Begrenzt Container-Logs auf maximal 30 MB pro Container (3 × 10m), deaktiviert den docker-proxy-Userland-Prozess zugunsten von Kernel-NAT ("userland-proxy": false), aktiviert Live-Restore und definiert saubere /24-Bridge-Subnetze.

ERWARTETE AUSGABE
 Storage Driver: overlay2
 Logging Driver: json-file
 Live Restore Enabled: true
§ 03

Schritt 3: Den berüchtigten Docker-UFW-Firewall-Bypass auf Netcup verhindern

Dies ist das am häufigsten übersehene Sicherheitsrisiko auf selbstverwalteten Linux-Servern: Wenn Sie ufw aktivieren (ufw default deny incoming) und anschließend einen Container mit ports: - "5432:5432" oder - "8080:8080" starten, ändert Docker die PREROUTING-NAT-Tabelle des Kernels, noch bevor die ufw-before-input-Filterkette überhaupt ausgewertet wird. Dadurch steht Port 5432 oder 8080 weltweit offen im Internet, obwohl ufw status lediglich die Ports 22, 80 und 443 als geöffnet anzeigt!

Um zu verstehen, warum das passiert, muss man den Weg eines Netzwerkpakets durch den Linux-Netfilter-Stack betrachten: Wenn ein Paket von außen auf Port 5432 Ihrer öffentlichen Netcup-IPv4-Adresse eintrifft, durchläuft es zuerst die Kette nat PREROUTING. Dort greift Dockers DNAT-Regel und schreibt die Ziel-IP von Ihrer Server-IP auf die interne Container-IP (172.20.0.2:5432) um. Da die Zieladresse nun nicht mehr der Host selbst ist, sondern ein geroutetes Bridge-Subnetz (br-xxxx), biegt der Kernel am Routing-Entscheidungspunkt in die Kette filter FORWARD statt in filter INPUT ab. Sämtliche ufw deny-Standardregeln befinden sich jedoch in der INPUT-Kette (ufw-before-input), während Docker in der FORWARD-Kette ganz oben seine eigene DOCKER-Kette einhängt und das Paket direkt an den Container durchlässt.

Aus genau diesem Grund reserviert die Docker Engine am Anfang der FORWARD-Kette eine spezielle Kette namens DOCKER-USER, die immer vor den automatisch generierten DOCKER-Regeln ausgewertet wird und bei einem Neustart von dockerd erhalten bleibt. Noch wirkungsvoller auf einem Netcup VPS oder Root-Server ist die Kombination aus drei Verteidigungsschichten: Binden Sie interne Container-Ports strikt an das Loopback-Interface (127.0.0.1:5432:5432), aktivieren Sie die zustandsbehaftete Netcup SCP Hypervisor-Firewall (die außerhalb Ihrer VM direkt am Host-Switch filtert) und härten Sie optional die DOCKER-USER-Kette.

Kontrollieren Sie nach jedem Deployment mit sudo ss -tulnp, welche Prozesse und Container tatsächlich an wildcard-fähigen Adressen (0.0.0.0 oder [::]) lauschen. Auf einem sauber konfigurierten Produktionsserver sollten auf 0.0.0.0 ausschließlich sshd (Port 22) und Ihr Reverse-Proxy (nginx, caddy oder traefik auf Port 80/443) erscheinen, während alle Datenbank-, Redis- und Applikations-Container entweder gar keinen Host-Port veröffentlichen (Zugriff über ein gemeinsames Docker-Bridge-Netzwerk) oder strikt an 127.0.0.1 gebunden sind:

  • ▪ Schicht 1 — Explizites Loopback-Binding in der compose.yaml: Schreiben Sie immer 127.0.0.1:8080:8080 statt 8080:8080 für Backend-Dienste, die über einen lokalen Nginx/Caddy-Reverse-Proxy angesprochen werden.
  • ▪ Schicht 2 — Zustandsbehaftete Netcup SCP Hypervisor-Firewall: Erlauben Sie im Netcup Server Control Panel (servercontrolpanel.de → Network → Firewall) eingehend nur TCP 22, 80, 443 sowie UDP 443 und setzen Sie die Standard-Ingress-Policy auf DROP. Da die SCP-Firewall außerhalb der VM auf dem Host-Switch arbeitet, können Dockers iptables-Regeln sie unmöglich umgehen!
  • ▪ Schicht 3 — DOCKER-USER-Kette in /etc/ufw/after.rules absichern: Fügen Sie explizite Drop-Regeln in die DOCKER-USER-Netfilter-Kette für Pakete ein, die über das öffentliche Interface (eth0/ens3) an private RFC1918-Container-Subnetze adressiert sind.
Docker-Container-Kapazität & Firewall-Architektur nach Netcup Server-Hardware
Netcup Server-ModellRAM & vCPU / KerneEmpfohlenes Docker-SpeicherbudgetTypische Docker-Workload-KapazitätEmpfohlener Firewall-Stack
VPS nano G11.5s2 GB ECC-RAM / 2 vCPU~1,4 GB für Container + 2 GB Swapfile3–5 schlanke Alpine / Go / Caddy Container127.0.0.1 Binding + Netcup SCP Edge-Firewall
VPS 500 G12.54 GB ECC-RAM / 4 vCPU~3,0 GB für Container + 4 GB Swapfile8–12 Container (WordPress, Redis, Postgres, Nginx)127.0.0.1 Binding + SCP Edge-Firewall + UFW
VPS 1000 G12.58 GB ECC-RAM / 6 vCPU~6,5 GB für Container + 4 GB Swapfile15–25 Container (Kompletter SaaS-Stack + Monitoring)127.0.0.1 Binding + SCP Firewall + DOCKER-USER Kette
RS 1000 G12.58 GB DDR5 ECC / 4 Dedizierte EPYC~6,8 GB für Container + 4–8 GB Swapfile25+ High-I/O-Container, CI-Runner & Datenbanken127.0.0.1 Binding + SCP Firewall + DOCKER-USER Kette
Exponierte Container-Sockets prüfen & Loopback-Binding testen
bash
# Interne Anwendungs- und Datenbank-Ports immer strikt an 127.0.0.1 binden:
docker run -d --name test-redis --restart unless-stopped -p 127.0.0.1:6379:6379 redis:7-alpine

# Alle lauschenden TCP/UDP-Sockets auf Ihrem Netcup-Server überprüfen:
# Auf 0.0.0.0 bzw. [::] dürfen nur sshd (22) und Ihr Reverse-Proxy (80/443) lauschen
sudo ss -tulnp

Befehlserklärung: Überprüft, dass redis-server ausschließlich an 127.0.0.1:6379 und nicht an 0.0.0.0:6379 lauscht.

ERWARTETE AUSGABE
tcp   LISTEN 0      4096       127.0.0.1:6379      0.0.0.0:*    users:(("dockerd",pid=1120,fd=14))

SICHERHEITSHINWEIS: Hinweis zur UNIX-Gruppe docker: Das Hinzufügen eines Benutzers mittels sudo usermod -aG docker deployadmin ist gleichbedeutend mit vollen root-Rechten, da jedes Mitglied der docker-Gruppe das Host-Wurzelverzeichnis / in einen Container mounten kann.

Veröffentlichen Sie niemals ungebundene Container-Ports (-p 5432:5432) auf einem Public VPS

Die Angabe -p 5432:5432 bindet an 0.0.0.0:5432 und leitet Pakete über die Netfilter-FORWARD-Kette weiter, wodurch UFW-INPUT-Regeln komplett umgangen werden. Stellen Sie internen Ports immer 127.0.0.1: voran (z. B. 127.0.0.1:5432:5432).

Häufige Fehlerbehebung

DIAGNOSE-GUIDE

[SYMPTOM] Container können keine externen DNS-Namen auflösen (Temporary failure in name resolution)

Ursache: Ubuntus systemd-resolved Stub-Listener läuft auf 127.0.0.53, was innerhalb eines isolierten Container-Netzwerk-Namespaces nicht erreichbar ist, wenn /etc/resolv.conf nur Loopback-Adressen enthält.

Lösung: Fügen Sie "dns": ["46.38.225.230", "1.1.1.1", "2a03:4000:0:1::e1e6"] (Netcups schnelle rekursive DNS-Resolver + Cloudflare DNS) in die /etc/docker/daemon.json ein und starten Sie Docker mit sudo systemctl restart docker neu.

[SYMPTOM] systemctl restart docker schlägt nach Änderungen an der /etc/docker/daemon.json fehl

Ursache: Nachgestellte Kommas oder JSON-Syntaxfehler in der /etc/docker/daemon.json oder widersprüchliche Start-Flags in /lib/systemd/system/docker.service.

Lösung: Validieren Sie die JSON-Syntax mit jq . /etc/docker/daemon.json und prüfen Sie das Protokoll über sudo journalctl -u docker.service -n 30 --no-pager.

[SYMPTOM] Das Docker-Bridge-Netzwerk (172.17.0.0/16) kollidiert mit einem internen WireGuard- oder OpenVPN-Subnetz

Ursache: Docker vergibt standardmäßig 172.17.0.0/16 bis 172.31.0.0/16, sofern kein default-address-pools-Block definiert ist.

Lösung: Definieren Sie einen konfliktfreien Adresspool unter "default-address-pools" in der /etc/docker/daemon.json (siehe Schritt 2) und erstellen Sie bestehende Netzwerke mit docker network prune neu.

Häufig gestellte Fragen (FAQ)

GEPRÜFTE ANTWORTEN

Läuft Docker problemlos auf einem kompakten Netcup VPS nano G11.5s?

Ja! Da auch der VPS nano G11.5s auf echter KVM-Virtualisierung mit 2 GB ECC-RAM und 60 GB SSD-Speicher basiert, führt er problemlos 3 bis 5 leichtgewichtige Alpine-, Go- oder Nginx-Container aus. Für größere Stacks mit MariaDB/PostgreSQL und Redis empfehlen wir den VPS 500 G12.5 (4 GB ECC-RAM) oder den VPS 1000 G12.5 (8 GB ECC-RAM).

Sollte ich meinen Netcup-Server für Docker overlay2 mit ext4 oder XFS formatieren?

Sowohl ext4 (Standard unter Ubuntu/Debian) als auch XFS (mit ftype=1, Standard unter AlmaLinux/Rocky) werden von Docker als Tier-1-Dateisysteme für den overlay2-Storage-Treiber vollständig unterstützt.

Wie bereinige ich ungenutzte Docker-Images und Build-Caches sicher auf einer Netcup-SSD?

Prüfen Sie die Belegung mit docker system df und führen Sie wöchentlich docker builder prune -af && docker image prune -af --filter "until=168h" aus, um verwaiste Layer freizugeben, ohne benannte Daten-Volumes (Named Volumes) anzutasten.

Warum blieb mein Container-Port aus dem Internet erreichbar, obwohl ich ufw deny 8080 ausgeführt habe?

Weil Docker seine Port-Forwarding-Regeln in die Netfilter-Ketten PREROUTING und FORWARD einfügt, während ufw deny 8080 nur die INPUT-Kette filtert. Binden Sie interne Ports immer an 127.0.0.1:8080:8080 und aktivieren Sie zusätzlich die Netcup SCP Stateful Firewall.

QUELLEN // GEPRÜFTE TECHNISCHE DOKUMENTATION

WEITERFÜHREND // EMPFOHLENE ARCHITEKTUR-AUDITS

Gutscheine →