Deployment guide

Running a Minecraft server in Docker without the footguns

Docker makes a Minecraft server reproducible, upgradeable and trivially movable between machines — and it introduces three specific ways to lose data or expose your server that a plain install does not have. The container itself is the easy part. Getting volumes, memory limits and port publishing right is what separates a setup you can rebuild in a minute from one you are afraid to touch.

What Docker actually buys you

The real wins are unglamorous and substantial: pinned versions, so a server does not silently change under you; a config you can commit, so the setup is described in a file rather than in someone's memory; and portability, so moving to a different host means copying a compose file and a data directory rather than reinstalling Java and rediscovering every setting. Rolling back a bad update becomes changing a tag instead of an archaeology project.

What it does not buy you is performance. A JVM in a container runs at essentially native speed — anyone promising a speed-up from containerisation is selling something. If your server is slow, profile it; the packaging is not the cause.

The three things to get right

VolumesThe server's data directory must live on a named volume or bind mount. Anything else dies with the container
MemoryContainer limit must exceed the JVM heap by roughly a gigabyte, or the kernel kills the process
Port publishingPublishing binds on the host, by default on every interface — this is how backends end up public
Restart policySet one, so the server comes back after a host reboot without manual intervention
Version pinningPin the image tag and the Minecraft version. `latest` means your server changes when you were not looking
EULAAccepted via an environment variable in every mainstream image — a first-run failure, not a mystery

Volumes: the one that eats worlds

A container's own filesystem is disposable by design. Everything written inside it that is not on a volume disappears when the container is removed — and you remove containers routinely, because that is how you change an environment variable or update an image. The failure is not exotic: someone edits a setting, recreates the container, and the world is gone.

Mount the server's data directory to a named volume or a bind mount on the host, and confirm it works before you have anything to lose. Stop the container, remove it, start a fresh one, and check the world is still there. Doing this deliberately on day one is much better than discovering it on day ninety. Whatever you choose, back the data up somewhere off the host — a volume protects you from container churn, not from the disk failing.

Memory: two limits that must not match

There are two independent numbers here and setting them equal is a trap. The JVM heap (`-Xmx`) is what Minecraft allocates into. The container memory limit is what the kernel permits the whole process to use — and the process needs more than the heap: metaspace, thread stacks, direct byte buffers, and the JVM's own overhead.

Set the container limit equal to the heap and the process will exceed it under load and be killed, producing a server that dies at peak hour with no Java error to explain it. Leave roughly a gigabyte of headroom between the two. The RAM guide covers how to pick the heap size itself — and the same warning applies here as everywhere: bigger is not better.

Networking: how backends end up on the public internet

This is the security footgun. Publishing a container port maps it onto the host, and unless you say otherwise, it binds on all interfaces. For a single public server that is what you want. For a backend behind a proxy, it is exactly wrong: you have taken a server that should only accept connections from your proxy and made it reachable by anyone who scans the address.

That matters far more than it sounds, because backends behind a proxy typically run with online-mode disabled — the proxy does the authentication. A publicly reachable backend in that state will let anyone connect as any username, including an administrator, as covered in the server.properties reference.

Pterodactyl is this, with a panel on top

If you would rather not manage compose files, Pterodactyl runs each server in its own container and gives you a web panel, users and per-server resource limits over the top. The same fundamentals apply underneath — volumes hold the data, containers have memory limits, ports are published — and its allocation model is a nicer way to handle the port question than raw publishing. Protecting one is covered in Pterodactyl DDoS protection.

Containers are not a security boundary against attacks

Worth being blunt about: Docker isolates processes from each other on a host. It does nothing about traffic arriving at that host. A volumetric flood saturates the uplink and takes down every container on the machine at once, and a bot join-flood reaches the containerised server exactly as it would a bare-metal one. If anything, a single host running several containerised servers concentrates the blast radius. Filtering belongs upstream, on a network built to absorb it — the container is where your server runs, not what protects it.

Common questions

Should I run my Minecraft server in Docker?+

It is a good fit if you value reproducibility — pinned versions, a config you can commit, and a server you can move to another machine by copying two things. It adds little overhead for a Java process. It is a poor fit if you are not comfortable with volumes and networking, because the failure modes involve deleting worlds and exposing ports rather than merely not working.

How do I stop Docker from deleting my Minecraft world?+

Put the server's data directory on a named volume or bind mount, never inside the container's writable layer. Anything not on a volume lives and dies with the container, so the moment you rebuild to change a setting, an unmounted world is gone. Verify it by stopping and removing the container deliberately, then starting a new one and confirming the world is still there.

How much memory should I give a Minecraft Docker container?+

Set the container limit above the JVM heap, not equal to it. The JVM needs metaspace, thread stacks and buffers beyond -Xmx, so a container capped at exactly the heap size will be killed by the kernel under load. Leaving roughly a gigabyte of headroom between the heap and the container limit avoids a whole category of confusing restarts.

Why can people connect to my Docker Minecraft server directly, bypassing my proxy?+

Because the container is publishing its port to every interface. Publishing binds the port on the host, and by default that means all addresses — so the backend that should only be reachable from your proxy is reachable from the internet. Bind published ports to a specific interface, or use a Docker network so backends are only reachable from the proxy container.

Does Docker protect my Minecraft server from DDoS attacks?+

No. A container is a process isolation boundary, not a network defence. Attack traffic that reaches the host reaches the container, and a saturated uplink takes everything on the machine offline regardless of how it is packaged. Containerisation and DDoS protection solve unrelated problems.

Containerised, pinned and backed up — and still one flood away from offline? Start free with Arvoris — one DNS record, no plugin, works with any host or container setup.

Related reading

PterodactylServer RAMserver.properties

Your next attack is already scheduled.
Be behind the edge when it lands.

We take care of security so you can branch out. Free plan, no card, one DNS record — if it doesn't hold, you lost five minutes.