From 3c89075eaae5230eb0dcac92b5bf95a09a673844 Mon Sep 17 00:00:00 2001 From: Evan Date: Sat, 17 Jan 2026 23:43:05 -0600 Subject: [PATCH] add Dockerfile, docker-compose, dependencies, and documentation --- Dockerfile | 22 ++++++++++++ README.md | 69 ++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 22 ++++++++++++ mcrcon | 4 +++ start-server.sh | 42 +++++++++++++++++++++++ template/eula.txt | 1 + template/server.properties | 9 +++++ 7 files changed, 169 insertions(+) create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 docker-compose.yml create mode 100644 mcrcon create mode 100644 start-server.sh create mode 100644 template/eula.txt create mode 100644 template/server.properties diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8198f4f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +# extract mcrcon +FROM debian:bookworm-slim AS builder + +ADD https://github.com/Tiiffi/mcrcon/releases/download/v0.7.2/mcrcon-0.7.2-linux-x86-64-static.zip /usr/bin/mcrcon.zip +RUN apt-get update && apt-get install -y unzip + +RUN unzip -j /usr/bin/mcrcon.zip -d /usr/bin/mc-rcon && chmod a+x /usr/bin/mc-rcon/mcrcon + + +# actual image +FROM eclipse-temurin:21 + +COPY --from=builder /usr/bin/mc-rcon /usr/bin/mc-rcon +COPY start-server.sh /usr/bin/start-server.sh +RUN chmod a+x /usr/bin/start-server.sh +COPY mcrcon /usr/bin/mcrcon +RUN chmod a+x /usr/bin/mcrcon +COPY template/ /defaults/ + +WORKDIR /minecraft_data +ENTRYPOINT ["/usr/bin/start-server.sh"] + diff --git a/README.md b/README.md new file mode 100644 index 0000000..dc47316 --- /dev/null +++ b/README.md @@ -0,0 +1,69 @@ +# Minecraft Docker Server +A docker image and compose build for running and controlling a Minecraft server from inside a Docker container. +* Supports any version of Minecraft; you just need a link to the server.jar + * tested on 1.21, more to come +* Server console access via [RCON](https://minecraft.wiki/w/RCON) + * uses [Tiiffi/mcrcon](https://github.com/Tiiffi/mcrcon) as a prepackaged RCON client +* All server files stored in a Docker volume +* Graceful shutdown handling (SIGTERM / SIGINT) + +## Usage +Requires [Docker](https://docs.docker.com/engine/install/), [Git](https://git-scm.com/install/), and a clone of this repository: +```sh +git clone https://gitea.jovan04.com/evan/minecraft-docker && cd minecraft-docker +``` + +### Build the Image +```sh +docker build -t minecraft_server . +``` + +### Run with Docker Compose +`docker-compose.yml` (included in this repository): +```sh +docker compose up -d +``` +(or `docker-compose` for older versions of Docker Compose) + +### First Startup +On first startup (when the data volume is empty): +* `server.properties` is created from a template +* `eula.txt` is generated and automatically accepted +* A default RCON configuration is written +* `server.jar` is downloaded from a provided link + +On subsequent startups, existing files are reused unchanged and environment variables are unused. + +### RCON Access +Minecraft implements the Remote Console (RCON) protocol, which allows server administrators to remotely execute commands. See more info [here](https://minecraft.wiki/w/RCON) and [here](https://developer.valvesoftware.com/wiki/Source_RCON_Protocol). RCON access is enabled automatically from inside the container. **Do not expose the RCON service to the internet directly!!!** RCON is not encrypted, so exposing this service can give hackers direct access to your server's administrator console. + +Log into the container: +```sh +docker exec -it minecraft_server bash +``` +Use the provided wrapper script (located at `/usr/bin/mcrcon`). The script dynamically reads the password from `/minecraft_data/server.properties`. + +Send a single command: +```sh +mcrcon list +mcrcon stop +``` + +For an interactive console (`Ctrl-C` or `Ctrl-D` to quit): +```sh +mcrcon +``` +Use this the same as typing into the actual server console + +### Graceful Shutdown Behavior +When the container receives SIGTERM or SIGINT: +1. A 10-second warning message is broadcast to the server +2. All chunks are saved manually +3. A `stop` command is sent to the Minecraft server +4. The server shuts down normally +5. The container waits up to a configurable timeout before force-exiting, in case large worlds take a long time to save or the server hangs + * default 120s; configure this by changing the `stop_grace_period` time in `docker-compose.yml` + +### Configuration +All Minecraft configuration is done through `server.properties`. Make any necessary changes before **building the image** to the file in this repository, or manually edit the `server.properties` file in the Minecraft server's Docker volume. More info about Docker volumes can be found [here](https://docs.docker.com/engine/storage/volumes). This container should work fine with a relative path in `docker-compose.yml` instead of a named volume. + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b145c90 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,22 @@ +services: + minecraft_server: + image: minecraft_server + container_name: minecraft_server + restart: unless-stopped + stop_grace_period: 120s + volumes: + - data:/minecraft_data + ports: + - 25565:25565 + environment: + # note: this is only used when initializing a new volume (technically, initializing a new server.properties file) + # if you want to change the password to your RCON server, edit it in your existing volume's server.properties file + MCRCON_PASS: YourPasswordHere + # note: again, this download URL is only used when initializing a new volume + # this is where the container will attempt to download a server.jar from + SERVER_JAR_DOWNLOAD_URL: https://piston-data.mojang.com/v1/objects/450698d1863ab5180c25d7c804ef0fe6369dd1ba/server.jar + +volumes: + data: + name: minecraft_server_data + diff --git a/mcrcon b/mcrcon new file mode 100644 index 0000000..30c532d --- /dev/null +++ b/mcrcon @@ -0,0 +1,4 @@ +#!/bin/bash +exec /usr/bin/mc-rcon/mcrcon -p "$( + grep '^rcon.password=' /minecraft_data/server.properties | cut -d= -f2- +)" "$@" diff --git a/start-server.sh b/start-server.sh new file mode 100644 index 0000000..7e2c10b --- /dev/null +++ b/start-server.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# initialize required files for an empty volume +# server.jar +if ! test -f /minecraft_data/server.jar; then + if [ -z "$SERVER_JAR_DOWNLOAD_URL" ]; then + echo "ERROR: SERVER_JAR_DOWNLOAD_URL not set for initial volume creation" + exit 1 + fi + wget -O /minecraft_data/server.jar "${SERVER_JAR_DOWNLOAD_URL}" +fi + +# server.properties +if ! test -f /minecraft_data/server.properties; then + if [ -z "$MCRCON_PASS" ]; then + echo "ERROR: MCRCON_PASS not set for initial volume creation" + exit 1 + fi + cat /defaults/server.properties | sed "s//${MCRCON_PASS}/" | tee /minecraft_data/server.properties +fi + +# eula.txt +if ! test -f /minecraft_data/eula.txt; then + cp /defaults/eula.txt /minecraft_data/eula.txt +fi + +export MCRCON_PASS=$(grep "^rcon.password=" /minecraft_data/server.properties | cut -d '=' -f 2- | head -n 1) + +# shutdown process +function shutdown { + echo "stopping Minecraft server..." + /usr/bin/mc-rcon/mcrcon -p ${MCRCON_PASS} -w 5 "say Server is restarting!" save-all stop + wait $SERVER_PID +} + +trap shutdown SIGTERM SIGINT + +java -jar /minecraft_data/server.jar --nogui & +SERVER_PID=$! + +wait $SERVER_PID + diff --git a/template/eula.txt b/template/eula.txt new file mode 100644 index 0000000..02dccd9 --- /dev/null +++ b/template/eula.txt @@ -0,0 +1 @@ +eula=true diff --git a/template/server.properties b/template/server.properties new file mode 100644 index 0000000..66ba565 --- /dev/null +++ b/template/server.properties @@ -0,0 +1,9 @@ +# Template server.properties file that allows remote control of the server +# see https://minecraft.wiki/w/RCON +broadcast-rcon-to-ops=true +enable-rcon=true +# don't change the next line! initializing a new Docker volume will automatically populate +rcon.password= +rcon.port=25575 +# the rest of the settings are automatically generated on server startup +