When this guide is the right one
Use this runbook if your Minecraft container starts normally, but players outside the server cannot connect. Typical symptoms are:
Connection refused- connection timeouts
- the server works on
localhost, but not via the public IP docker compose pslooks healthy, yet nobody can join
The goal is simple: make sure Minecraft Java traffic can reach your server on TCP port 25565 from the internet.
60-second quick check
- Confirm Docker published
25565:25565. - Confirm the Linux host is listening on port 25565.
- Allow TCP
25565in your host firewall. - Allow TCP
25565in the Hetzner Cloud Firewall. - Test from a different network.
Prerequisites
- A Minecraft Java server running in Docker or Docker Compose
- A public IPv4 or IPv6 on your Hetzner server
- SSH access to the Linux host
If you have not deployed the server yet, start with Setting up a Minecraft Server on a Hetzner Cloud Server with Docker Compose.
Step 1: Verify that Docker actually publishes the game port
Start with the local truth. If Docker never published the port, firewall changes will not help.
docker compose ps
docker ps --format 'table {{.Names}}\t{{.Ports}}'
You want to see 25565/tcp published on the host, for example:
0.0.0.0:25565->25565/tcp
:::25565->25565/tcp
If nothing is published, fix the Compose file first:
services:
mc:
image: itzg/minecraft-server:latest
ports:
- "25565:25565"
Then apply the change:
docker compose up -d
Step 2: Check whether the host is listening on 25565
Next, confirm that the Linux host sees a listener on the public side.
sudo ss -tlnp | grep 25565
If the command returns nothing, one of these is usually true:
- the container is not running
- the port mapping is missing
- the service failed during startup
In that case, inspect the logs:
docker compose logs -f
Step 3: Open the Linux host firewall
If you use UFW, allow Minecraft explicitly:
sudo ufw allow 25565/tcp
sudo ufw status
If you manage rules via raw iptables or nftables, make sure there is an inbound allow rule for TCP 25565.
Do not remove SSH access while testing. If your firewall is very restrictive, keep 22/tcp allowed from your admin IP before changing anything else.
Step 4: Open the Hetzner Cloud Firewall
Hetzner Cloud Firewalls sit outside the server. That means your Linux host can be configured correctly and traffic can still be dropped before it ever reaches the VM.
In the Hetzner console:
- Open your project.
- Go to
Firewalls. - Create or edit the firewall attached to the Minecraft server.
- Add an inbound rule for
TCP, port25565, source0.0.0.0/0if you want public access. - If you also want IPv6 players to connect, add
::/0as a source as well.
For the initial test, keep the rule simple. Once joining works, you can tighten other ports such as SSH.
Step 5: Test from outside the server
Do not test only from the host itself. Use one of these instead:
- join from your normal Minecraft client on a different connection
- ask a friend to connect
- test from a mobile hotspot
Your Java client should connect to:
YOUR_SERVER_IP:25565
If the connection works now, the network path is fixed and you can move on to a nicer address with Minecraft Domain Without a Port: How to Set Up an SRV Record.
Common mistakes
| Symptom | Likely cause | Fix |
|---|---|---|
docker ps shows no published ports | Compose file has no ports mapping | Add "25565:25565" and recreate |
| Port is open in UFW, but still blocked publicly | Hetzner Cloud Firewall still drops traffic | Add inbound TCP 25565 there as well |
| Port scan says closed, logs look normal | Wrong protocol | Use TCP for a Java server |
| RCON works internally, but players cannot join | Only admin path works | Publish the Minecraft game port, not just RCON |
Security note
Open only the port you actually need for players. For a normal Minecraft Java setup, that is usually TCP 25565 and nothing else. Do not expose RCON just because you want admin access. Keep administrative access on the Docker host or inside a private Docker network.
FAQ
Should I bind the game port only to one IP?
Only if you know exactly why you need that. For most single-server setups, the default public bind is fine.
What about the Query port?
Only enable and expose Query if you intentionally use it. A normal Java server does not need it for players to join.
Next steps
- Want a cleaner address? Read Minecraft Domain Without a Port: How to Set Up an SRV Record.
- Still in initial setup? Go back to the Hetzner Docker setup guide.