Why
I’ve been running a Java Minecraft world (with Bedrock players via Geyser) in tmux. I moved it to Docker for easier updates, backups, and restarts. Along the way I hit:
failed to register layer: ... no space left on device- Client saying: “Outdated client, please use 1.21.9 Pre-Release 2”
- Wanting config in a neat
.envand no whitelist
Here’s exactly what I did.
Folder layout
~/minecraft/
├─ docker-compose.yml
├─ .env
└─ plugins/
.env (secrets & knobs)
Use the latest stable (not snapshots/pre-releases) by setting VERSION=LATEST.
# Minecraft server configuration
EULA=TRUE
TYPE=PAPER
VERSION=LATEST
MEMORY=4G
USE_AIKAR_FLAGS=true
# RCON (remote console)
ENABLE_RCON=true
RCON_PASSWORD=superSecretPassword123
I don’t use a whitelist, so no
WHITELIST/ENFORCE_WHITELISTvariables.
docker-compose.yml
services:
mc:
image: itzg/minecraft-server:latest
container_name: mc
restart: unless-stopped
ports:
- "25565:25565" # Java
- "19132:19132/udp" # Bedrock via Geyser plugin
env_file:
- .env
volumes:
- mc-data:/data
- ./plugins:/plugins:ro
volumes:
mc-data: {}
The
version:key in Compose is obsolete now, so I dropped it.
Add Geyser (and optional Floodgate) as plugins
mkdir -p ~/minecraft/plugins
cd ~/minecraft/plugins
# Geyser (Spigot/Paper)
wget https://download.geysermc.org/v2/projects/geyser/versions/latest/builds/latest/downloads/spigot -O Geyser-Spigot.jar
# Floodgate (optional: Bedrock accounts without Java linking)
wget https://download.geysermc.org/v2/projects/floodgate/versions/latest/builds/latest/downloads/spigot -O Floodgate-Spigot.jar
Start it up:
docker compose up -d
On first run, Geyser writes its config to /data/plugins/Geyser-Spigot/. Open UDP 19132 on your firewall.
Hit a wall: /var ran out of space
Docker stores layers at /var/lib/docker by default. My /var LV was tiny:
Quick cleanup
docker system df
docker system prune -f
docker builder prune -af
sudo apt-get clean
sudo journalctl --vacuum-size=100M
If that’s not enough, you have two good options:
Option A — Move Docker’s data off /var
sudo systemctl stop docker
sudo mkdir -p /home/docker
sudo rsync -aHAX --info=progress2 /var/lib/docker/ /home/docker/
echo '{ "data-root": "/home/docker" }' | sudo tee /etc/docker/daemon.json
sudo systemctl start docker
docker info | grep "Docker Root Dir"
If all looks good, free the old space:
sudo rm -rf /var/lib/docker/*
Option B — Grow /var (LVM)
Check free space in the VG:
sudo vgdisplay # look for "Free PE / Size"
If available, extend /var by +5G:
sudo lvextend -L +5G /dev/mapper/ubuntu--vg-var
sudo resize2fs /dev/mapper/ubuntu--vg-var
The version mismatch: pre-release vs stable
My logs showed:
That happens if the server pulls a pre-release build (or if VERSION=LATEST). Fix:
- Ensure
.envhas:VERSION=LATEST_RELEASE - Recreate:
docker compose down docker compose pull docker compose up -d - Verify:
docker logs mc | grep "Starting minecraft server version" # -> Starting minecraft server version 1.21.1 (example)
Tip: If you want to pin and avoid auto-updates entirely, set
VERSION=1.21.1(or whatever stable you’ve validated).
No whitelist
Because I don’t set WHITELIST/ENFORCE_WHITELIST, anyone can join (subject to online-mode, bans, and Geyser/Floodgate auth settings). Manage ops/permissions via:
docker exec -it mc rcon-cli "op YourJavaIGN"
(or edit /data/ops.json).
Backup & updates
- World/data live under the
mc-datavolume → back up/dataregularly. - Update cleanly:
docker compose pull && docker compose up -d - Watch space:
watch -n5 'df -h /var; docker system df'
TL;DR
- Put Geyser/Floodgate jars in
./pluginsand expose 19132/udp. - Keep configs in
.env. - Fix
/varspace by pruning, moving Docker’s data-root, or extending/varvia LVM. - Verify version in logs after each change.
Happy block-breaking! 🧱🚀