Adam's blog: Join to start a Minecraft server
Multiple Minecraft servers are running on my cheap VPS with limited RAM – how to make accessing them as user-friendly as possible?
All of my servers are running almost effortlessly thanks to the amazing Docker Minecraft server. However, in a situation when one of the servers wants to eat at least 6 GiB of memory while the maximal memory available is 8 GiB, all servers can’t be running at the same time. Some of them must be stopped.
AutoStop & AutoPause
The amazing docker image provides the option to pause (to free up the CPU) or to stop the server. Supposedly, when a pause happens, a knock server is fired up on the same port and listens for an incoming TCP connection. When the TCP connection is established, the Minecraft server is started again. Unfortunately, this did not work for me (the server was always running when I checked the RAM usage) and I did not feel like debugging. I wanted something better anyway.
Recreating the behaviour
I liked the idea of a knock server starting the server again. For that, I have written a simple bash script that checks if a docker container is running and if not, creates a NetCat server that waits for a connection. When a TCP connection is established, the Minecraft server is started. To shutdown the server again, I have set AutoStop to shut down the server after one hour without any players:
#!/bin/bash
# Example: the container is named mc_server1 and is using port 25565
# -> run with ./autostart server1 25565
set -u
SERVER="$1"
PORT="$2"
echo "Will check for $SERVER on port $PORT"
CONTAINER="mc_$SERVER"
while true; do
if docker ps | fgrep --quiet "$CONTAINER"; then
sleep 10
continue
fi
netcat -lw 1 0.0.0.0 "$PORT" &&
echo "Starting $SERVER" &&
docker start "$CONTAINER"
done
Making it user-friendly
This is nice, but the server starts as soon as any player (or bots) checks if the server is online (does not even have to try to establish a player session). As I am using whitelists on the server, I would want the autostart script to respond only to the whitelisted users. For that to work, I asked my brother (as he has much more Minecraft-related experience than me) to create a script that would:
- listen on the same port as the Minecraft server
- show a message to the users that the server is currently turned off
- allow the user to join the server, which will trigger the autostart process
You can download the mock Minecraft server here. The only required change to my autostart script was to replace the netcat
with the custom Python script:
#!/bin/bash
# Example: the container is named mc_server1 and is using port 25565
# -> run with ./autostart server1 25565
set -u
SERVER="$1"
PORT="$2"
echo "Will check for $SERVER on port $PORT"
CONTAINER="mc_$SERVER"
while true; do
if docker ps | fgrep --quiet "$CONTAINER"; then
sleep 10
continue
fi
python mock-server.py "/ot/minecraft-autostart/$SERVER.json" &&
echo "Starting $SERVER" &&
docker start "$CONTAINER"
done
What users see
The final workflow is pretty rewarding to see:
The server is offline - join to start the server
Notification that the server is starting now
Wait few moments for the real server to start
The real server is running