Docker fuer Minecraft-Server: Vor- und Nachteile
Nehmen wir an, du betreibst drei Minecraft-Server: Lobby, Survival und Minigames. Jeder braucht seine eigene Java-Version, eigene Plugins, eigene JVM-Einstellungen. Du aktualisierst einen und der andere geht kaputt. Kommt dir bekannt vor? Docker loest genau dieses Problem. Jeder Server lebt in einem isolierten Container mit eigener Umgebung, und sie stoeren sich nicht gegenseitig.
Aber Docker ist kein Allheilmittel. Es hat echte Einschraenkungen, besonders fuer Gameserver, wo jede Millisekunde zaehlt. In diesem Artikel schauen wir uns an, wann Docker wirklich nuetzlich ist und wann es mehr Probleme schafft als es loest.
Warum Docker fuer Minecraft
Die Kernidee von Docker ist Isolation. Jeder Container enthaelt alles, was die Anwendung braucht: Betriebssystem, Java, Server-Software, Plugins. Wenn ein Container abstuerzt, laufen die anderen weiter. Wenn du Java von 17 auf 21 fuer einen Server upgraden musst, betrifft das die anderen nicht.
Reproduzierbarkeit. Ein Docker-Image enthaelt eine fixierte Umgebung. Was auf deiner Testmaschine funktioniert, funktioniert identisch in Produktion. Kein "bei mir hat es funktioniert" mehr - wenn das Image baut, laeuft es gleich auf jedem Host mit Docker.
Einfaches Deployment. Ein neuer Server ist ein docker-compose up -d. Keine manuelle Java-Installation, keine Umgebungsvariablen einrichten, keine JAR-Dateien von Hand herunterladen. Alles steht in der docker-compose.yml, und jedes Teammitglied kann eine identische Umgebung aufsetzen.
Ressourcen-Isolation. Docker nutzt cgroups zur Begrenzung von CPU und Speicher. Wenn der Minigames-Server ploetzlich allen Speicher frisst wegen eines Plugin-Lecks, reisst er nicht Lobby und Survival mit. Der OOM-Killer erwischt nur diesen einen Container.
Einfache Backups. Daten liegen in Docker Volumes oder Bind Mounts. Backup heisst Verzeichnis kopieren. Restore heisst Verzeichnis ersetzen und Container neustarten. Keine komplizierten Prozeduren.
Das itzg/minecraft-server Image
Du musst kein eigenes Dockerfile von Grund auf schreiben. Das itzg/minecraft-server Image ist der De-facto-Standard fuer MC in Docker. Es unterstuetzt Paper, Spigot, Fabric, Forge, Velocity, BungeeCord und dutzende andere Server-Plattformen.
Minimaler Start:
docker run -d \
--name mc-server \
-p 25565:25565 \
-e EULA=TRUE \
-e TYPE=PAPER \
-e VERSION=1.21.4 \
-v mc-data:/data \
itzg/minecraft-server
Der Container laedt Paper 1.21.4 herunter, akzeptiert die EULA, generiert eine Welt und hoert auf Port 25565. Daten bleiben im Volume mc-data erhalten.
Nuetzliche Umgebungsvariablen:
MEMORY=4G- 4 GB fuer die JVM zuweisen (setzt -Xms und -Xmx)TYPE=PAPER- Server-Typ (PAPER, SPIGOT, FABRIC, FORGE, VELOCITY, BUNGEECORD)VERSION=1.21.4- Minecraft-VersionONLINE_MODE=FALSE- fuer Server hinter einem Proxy (Velocity/BungeeCord)OPS=player1,player2- Operator-ListeDIFFICULTY=hard- SchwierigkeitsgradVIEW_DISTANCE=10- SichtweiteMAX_PLAYERS=100- Spieler-LimitJVM_OPTS=-XX:+UseG1GC -XX:+ParallelRefProcEnabled- zusaetzliche JVM-Flags
Docker Compose: einzelner Server
Fuer Produktion immer docker-compose statt nacktem docker run verwenden. Eine Konfigurationsdatei ist einfacher zu pflegen, zu versionieren und mit Kollegen zu teilen.
version: "3.8"
services:
minecraft:
image: itzg/minecraft-server:latest
container_name: mc-survival
restart: unless-stopped
environment:
EULA: "TRUE"
TYPE: PAPER
VERSION: "1.21.4"
MEMORY: "6G"
VIEW_DISTANCE: "12"
MAX_PLAYERS: "50"
DIFFICULTY: "hard"
SPAWN_PROTECTION: "0"
SNOOPER_ENABLED: "FALSE"
JVM_OPTS: >-
-XX:+UseG1GC
-XX:+ParallelRefProcEnabled
-XX:MaxGCPauseMillis=200
-XX:+UnlockExperimentalVMOptions
-XX:+DisableExplicitGC
-XX:G1NewSizePercent=30
-XX:G1MaxNewSizePercent=40
-XX:G1HeapRegionSize=8M
-XX:G1ReservePercent=20
-XX:G1MixedGCCountTarget=4
-XX:InitiatingHeapOccupancyPercent=15
-XX:G1MixedGCLiveThresholdPercent=90
-XX:SurvivorRatio=32
-XX:+PerfDisableSharedMem
-XX:MaxTenuringThreshold=1
volumes:
- ./server-data:/data
ports:
- "25565:25565"
deploy:
resources:
limits:
memory: 8G
cpus: "4.0"
reservations:
memory: 6G
cpus: "2.0"
Beachte den Abschnitt deploy.resources. Wir setzen harte Limits: der Container kann nicht mehr als 8 GB RAM und 4 CPU-Kerne nutzen. Gleichzeitig reservieren wir mindestens 6 GB und 2 Kerne. Das Docker-Speicherlimit muss hoeher als die JVM-MEMORY-Einstellung sein - Java verbraucht mehr als die Heap-Groesse (Metaspace, nativer Speicher, Threads).
Volumes: Welten, Plugins, Konfigurationen
Richtige Volume-Organisation ist der Schluessel zur bequemen Verwaltung. Du hast zwei Optionen: Docker Volumes und Bind Mounts.
Bind Mounts (empfohlen fuer MC) - ein bestimmtes Host-Verzeichnis in den Container mappen:
volumes:
- ./server-data:/data
Alle Server-Dateien landen in ./server-data auf dem Host. Du kannst Konfigurationen direkt bearbeiten, Plugins per scp kopieren, Backups mit normalem rsync machen.
Docker Volumes - von Docker verwalteter Speicher:
volumes:
- mc-data:/data
volumes:
mc-data:
Daten liegen in /var/lib/docker/volumes/mc-data/_data. Isolierter, aber weniger praktisch fuer direkten Zugriff.
Fuer Minecraft-Server sind Bind Mounts praktischer. Typische Struktur:
./server-data/
world/ # Oberwelt
world_nether/ # Nether
world_the_end/ # Ende
plugins/ # Plugin-JARs und Konfigurationen
server.properties
paper-global.yml
paper-world-defaults.yml
ops.json
whitelist.json
Um ein Plugin hinzuzufuegen, kopiere einfach die JAR nach ./server-data/plugins/ und starte den Container neu.
Netzwerk: Host vs. Bridge
Das ist eine kritische Entscheidung fuer Gameserver.
Bridge (Standard). Docker erstellt ein virtuelles Netzwerk. Traffic laeuft ueber NAT. Fuer die meisten Webanwendungen kein Problem. Fuer Minecraft - zusaetzliche Latenz. NAT verarbeitet jedes Paket, und bei 100 Spielern ist das spuerbar. Vorteil: Port-Forwarding, Netzwerk-Isolation.
Host Mode. Der Container nutzt den Netzwerk-Stack des Hosts direkt. Kein NAT, kein Overhead. Pakete gehen direkt zum Java-Prozess. Nachteil: keine Netzwerk-Isolation, der Container belegt Host-Ports.
services:
minecraft:
image: itzg/minecraft-server:latest
network_mode: host
environment:
EULA: "TRUE"
TYPE: PAPER
SERVER_PORT: "25565"
Fuer Gameserver: Host Mode verwenden. Der 1-3 ms Latenzunterschied mag trivial klingen, aber bei 20 Ticks pro Sekunde und dutzenden Spielern summiert sich das. Bridge Mode ist sinnvoll, wenn du Netzwerk-Isolation zwischen Containern brauchst oder mehrere Server auf verschiedenen Ports auf derselben Maschine betreibst.
Performance: Java in Containern
Java laeuft gut in Docker, aber es gibt Feinheiten.
Speicher. Die JVM erkennt cgroup-Limits und bestimmt den verfuegbaren Speicher korrekt (seit Java 10+ eingebaut). Wenn du MEMORY=6G mit einem Docker-Limit von 8G setzt, funktioniert alles. Aber setze das Docker-Limit nicht gleich der Heap-Groesse - die JVM braucht Speicher ueber den Heap hinaus (200-500 MB fuer Metaspace, Threads, native Puffer).
CPU. Docker nutzt CPU Shares und CFS Quota. Standardmaessig teilen sich Container die CPU proportional. Ein hartes Limit (cpus: "4.0") kann zu Throttling fuehren - eine GC-Pause kann nicht mehr als 4 Kerne nutzen, selbst wenn sie frei sind. Fuer einen einzelnen Server ist es besser, kein hartes CPU-Limit zu setzen und stattdessen cpu_shares zur Priorisierung zu verwenden.
Festplatte. Overlay2 (Dockers Standard-Dateisystem) fuegt minimalen Lese-Overhead hinzu. Aber bei intensivem Schreiben (Weltspeicherung, Logs) kann der Unterschied spuerbar sein. Bind Mounts umgehen das Overlay - direkter Zugriff auf das Host-Dateisystem. Ein weiterer Grund, Bind Mounts fuer Daten zu verwenden.
Netzwerk. Bridge vs. Host haben wir bereits besprochen. Wichtig: Im Bridge-Modus kannst du keine Jumbo Frames im Docker-Netzwerk aktivieren - die MTU ist fest. Bei grossen Mengen an Chunk-Daten, die zum Spieler fliegen, kann das die Paketanzahl erhoehen.
Multi-Server: Velocity + Paper
Die wahre Staerke von Docker zeigt sich bei Multi-Server-Setups. Eine einzige docker-compose.yml beschreibt die gesamte Infrastruktur.
version: "3.8"
services:
proxy:
image: itzg/bungeecord:latest
container_name: mc-velocity
restart: unless-stopped
environment:
TYPE: VELOCITY
MEMORY: "512M"
volumes:
- ./velocity-data:/server
ports:
- "25565:25577"
deploy:
resources:
limits:
memory: 1G
lobby:
image: itzg/minecraft-server:latest
container_name: mc-lobby
restart: unless-stopped
environment:
EULA: "TRUE"
TYPE: PAPER
VERSION: "1.21.4"
MEMORY: "2G"
ONLINE_MODE: "FALSE"
SERVER_PORT: "25566"
volumes:
- ./lobby-data:/data
expose:
- "25566"
deploy:
resources:
limits:
memory: 3G
survival:
image: itzg/minecraft-server:latest
container_name: mc-survival
restart: unless-stopped
environment:
EULA: "TRUE"
TYPE: PAPER
VERSION: "1.21.4"
MEMORY: "6G"
ONLINE_MODE: "FALSE"
SERVER_PORT: "25567"
volumes:
- ./survival-data:/data
expose:
- "25567"
deploy:
resources:
limits:
memory: 8G
minigames:
image: itzg/minecraft-server:latest
container_name: mc-minigames
restart: unless-stopped
environment:
EULA: "TRUE"
TYPE: PAPER
VERSION: "1.21.4"
MEMORY: "4G"
ONLINE_MODE: "FALSE"
SERVER_PORT: "25568"
volumes:
- ./minigames-data:/data
expose:
- "25568"
deploy:
resources:
limits:
memory: 6G
Beachte, dass Paper-Server expose statt ports verwenden - sie sind von aussen nicht erreichbar, nur ueber Velocity. Der Proxy veroeffentlicht Port 25565, nimmt Verbindungen an und leitet sie ueber Docker DNS an interne Server weiter (Service-Namen: lobby, survival, minigames).
In velocity.toml werden Server ueber Docker-Service-Namen referenziert:
[servers]
lobby = "lobby:25566"
survival = "survival:25567"
minigames = "minigames:25568"
try = ["lobby"]
Docker loest lobby automatisch zur Container-IP auf. Wenn ein Container neustartet und eine neue IP bekommt, aktualisiert sich das DNS.
Backups von Docker-Servern
Ein Backup eines Servers in Docker bedeutet, das Bind-Mount-Verzeichnis zu sichern. Aber es gibt einen wichtigen Punkt: du solltest keine Weltdateien kopieren, waehrend der Server schreibt.
Der richtige Ansatz:
#!/bin/bash
# backup.sh
BACKUP_DIR="/backups/minecraft"
DATE=$(date +%Y%m%d_%H%M%S)
# Autosave deaktivieren und finalen Save erzwingen
docker exec mc-survival rcon-cli save-off
docker exec mc-survival rcon-cli save-all
sleep 5
# Daten kopieren
tar czf "$BACKUP_DIR/survival-$DATE.tar.gz" ./survival-data/
# Autosave wieder aktivieren
docker exec mc-survival rcon-cli save-on
echo "Backup abgeschlossen: survival-$DATE.tar.gz"
Das itzg/minecraft-server Image enthaelt rcon-cli - du kannst Serverbefehle ausfuehren, ohne dich an die Container-Konsole anzuhaengen.
Zur Automatisierung - cron:
0 */4 * * * /opt/minecraft/backup.sh >> /var/log/mc-backup.log 2>&1
Backups alle 4 Stunden. Fuer groessere Server ziehe inkrementelle Backups mit borgbackup in Betracht.
Sicherheit
Docker-Container laufen standardmaessig als root innerhalb des Containers. Fuer einen Minecraft-Server ist das nicht kritisch (der Container ist isoliert), aber Vorsicht ist besser.
Nicht-Root-Benutzer. Das itzg/minecraft-server Image unterstuetzt UID/GID:
environment:
UID: 1000
GID: 1000
Read-Only-Dateisystem. Du kannst das Root-Dateisystem des Containers schreibgeschuetzt machen und Schreibzugriff nur fuer Daten erlauben:
services:
minecraft:
image: itzg/minecraft-server:latest
read_only: true
tmpfs:
- /tmp
volumes:
- ./server-data:/data
Capabilities entfernen. Unnoetige Linux Capabilities entfernen:
services:
minecraft:
image: itzg/minecraft-server:latest
cap_drop:
- ALL
cap_add:
- CHOWN
- SETUID
- SETGID
Niemals --privileged verwenden. Niemals. Das gibt dem Container vollen Zugriff auf den Host.
Images aktuell halten. docker-compose pull && docker-compose up -d aktualisiert Images und erstellt Container mit neuen Versionen neu.
Wann Docker nicht die richtige Wahl ist
Docker ist keine universelle Loesung. Hier sind Situationen, in denen es Komplexitaet ohne Nutzen hinzufuegt:
Einzelner Server auf dedizierter Maschine. Wenn du einen VPS mit einem Minecraft-Server hast, bietet Docker minimale Vorteile. Java ist bereits in der JVM isoliert, und Docker fuegt eine Abstraktionsschicht hinzu. Es ist einfacher, Java direkt zu installieren und ueber systemd zu starten.
Performance-kritische Setups. Wenn du jeden Tick aus einem Server mit 200+ Spielern herausquetschst, zaehlt jeder Overhead. Docker mit Bridge-Netzwerk fuegt Latenz hinzu. Overlay FS fuegt Schreibverzoegerung hinzu. cgroups fuegen CPU-Scheduling-Overhead hinzu. Mit Host Mode und Bind Mounts ist der Unterschied minimal, aber er existiert.
Keine DevOps-Erfahrung. Wenn du mit Docker nicht vertraut bist, wird das Debuggen von Problemen im Container schwieriger als auf einer nackten Maschine. Logs sind an einem anderen Ort, das Dateisystem ist geschichtet, das Netzwerk ist virtuell. Lerne Docker zuerst an weniger kritischen Projekten.
Shared Hosting. Panels wie Pterodactyl verwenden Docker bereits unter der Haube. Eine weitere Docker-Schicht darueber zu legen ergibt keinen Sinn.
Nuetzliche Befehle
Schnellreferenz fuer den taeglichen Betrieb:
# Container-Status
docker-compose ps
# Server-Logs (letzte 100 Zeilen, Echtzeit)
docker-compose logs -f --tail=100 survival
# Server-Konsole ueber rcon
docker exec mc-survival rcon-cli
# Einen Server neustarten ohne die anderen zu stoppen
docker-compose restart survival
# Images aktualisieren
docker-compose pull
docker-compose up -d
# Ressourcenverbrauch
docker stats
# Plugin in den Server kopieren
cp my-plugin.jar ./survival-data/plugins/
docker-compose restart survival
Zusammenfassung
Docker eignet sich hervorragend fuer Multi-Server-Setups, Testumgebungen und Situationen, in denen Reproduzierbarkeit wichtig ist. Das itzg/minecraft-server Image deckt 95% der Anwendungsfaelle ab. Host Networking entfernt den Netzwerk-Overhead, Bind Mounts geben direkten Dateizugriff, und cgroups schuetzen vor Speicherlecks in Plugins.
Aber wenn du einen Server auf einer Maschine hast - ein einfacher systemd-Service ist einfacher und etwas schneller. Docker loest Skalierungs- und Reproduzierbarkeitsprobleme. Wenn du diese Probleme nicht hast, sucht die Loesung nach einem Problem.
Starte mit docker-compose fuer einen Testserver. Lass ihn eine Woche laufen, beobachte die Performance, gewoehne dich an den Workflow. Wenn alles passt - migriere die Produktion. Wenn nicht - du verlierst nichts, Weltdateien lassen sich in ein paar Minuten zurueck auf einen nackten Server verschieben.
Schützen Sie Ihren Server vor DDoS-Angriffen
Kostenloser Schutz mit 5-Minuten-Einrichtung. 1 TB Traffic inklusive.
Kostenlos testenWeitere Artikel
Minecraft Server Backups: Daten bei Angriffen schützen
Vollstaendiger Guide zu Minecraft Server Backups: die 3-2-1 Regel, Cron-Automatisierung, inkrementelle Sicherungen mit borgbackup, Offsite-Speicherung via rclone, Live-Backups ohne Serverunterbrechung und schnelle Wiederherstellung nach Angriffen.
Minecraft Server auf Ubuntu Linux einrichten: Schritt-für-Schritt-Anleitung
Vollständige Anleitung zur Installation und Konfiguration eines Minecraft-Servers auf Ubuntu 22.04/24.04. Java 21, Paper, systemd, Firewall, JVM-Flags und Auto-Neustart.
Neuer Filterstandort in Russland - Moskau
MineGuard hat einen Filterstandort in Moskau gestartet. Spieler aus der GUS erhalten 30-40ms weniger Ping, während europäischer und ukrainischer Traffic weiterhin über Deutschland läuft.