Handle SIGTERM to stop Minecraft gracefully
- Set up SIGTERM signal trap to invoke stop_server - Ensure proper process exit and cleanup after the server stops - Create makefile to build, clean, and install builds
This commit is contained in:
parent
381bd9eeff
commit
297902a686
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
data
|
||||
.env
|
||||
screenlog.0
|
||||
|
@ -10,7 +10,7 @@ RUN groupadd -g 1000 minecraft && \
|
||||
|
||||
# Install scripting dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y curl gpg jq screen && \
|
||||
apt-get install -y curl gpg jq procps screen strace && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
17
Makefile
Normal file
17
Makefile
Normal file
@ -0,0 +1,17 @@
|
||||
CONTAINER = minecraft-minecraft-1
|
||||
|
||||
.PHONY: default build clean install
|
||||
default: build
|
||||
|
||||
build:
|
||||
docker compose build
|
||||
|
||||
clean:
|
||||
rm -f screenlog.0
|
||||
docker compose down --rmi all
|
||||
docker builder prune -f
|
||||
|
||||
install: build
|
||||
touch screenlog.0
|
||||
docker compose up -d && \
|
||||
docker logs -f $(CONTAINER)
|
13
README.md
13
README.md
@ -1,13 +1,24 @@
|
||||
# Minecraft Docker Image
|
||||
This Dockerfile sets up a Minecraft server based on the `debian-slim` image.
|
||||
|
||||
## Quick Start
|
||||
By running the following and building this image, you are agreeing to
|
||||
[Minecraft's EULA](https://www.minecraft.net/en-us/eula):
|
||||
```
|
||||
echo "EULA=true" > .env
|
||||
```
|
||||
|
||||
To build and test the image:
|
||||
Build the image using the Makefile:
|
||||
```
|
||||
make build
|
||||
```
|
||||
|
||||
Optionally, build _and_ run to test it:
|
||||
```
|
||||
make install
|
||||
```
|
||||
|
||||
Feel free to use `docker compose` directly to build and test:
|
||||
```
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
|
@ -1,6 +1,3 @@
|
||||
volumes:
|
||||
minecraft:
|
||||
|
||||
services:
|
||||
minecraft:
|
||||
build:
|
||||
@ -12,12 +9,10 @@ services:
|
||||
image: ${IMAGE:-minecraft}:${TAG:-latest}
|
||||
ports:
|
||||
- "0.0.0.0:25565:25565"
|
||||
#volumes:
|
||||
# - minecraft:/app/world
|
||||
environment:
|
||||
EULA: "${EULA:-false}"
|
||||
DEBUG: "${DEBUG:-false}"
|
||||
JVM_OPTS: "-Xms1G -Xmx2G"
|
||||
JVM_OPTS: "${JAVA_OPTS:--Xms1G -Xmx2G}"
|
||||
SETTINGS_gamemode: "${GAMEMODE:-survival}"
|
||||
SETTINGS_hardcore: "${HARDCORE:-false}"
|
||||
SETTINGS_motd: "${MOTD:-A Minecraft Server}"
|
||||
|
@ -1,5 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check if the minecraft screen is still running
|
||||
check_screen() {
|
||||
if [ "$(screen -ls | grep -cE '[0-9]+\.minecraft')" -eq 1 ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to stop the server gracefully
|
||||
stop_server() {
|
||||
if check_screen; then
|
||||
# Run 'stop' inside screen and wait for the screen to exit
|
||||
/usr/bin/screen -p 0 -S minecraft -X eval 'stuff "stop"\015'
|
||||
wait "$STRACE_PID"
|
||||
|
||||
# Stop tail -f to stdout
|
||||
if kill -0 "$TAIL_PID" 2>/dev/null; then
|
||||
kill "$TAIL_PID"
|
||||
fi
|
||||
|
||||
# Check only this script is running (PID 1) and pgrep (2 PIDs total)
|
||||
PGREP_OUTPUT="$(pgrep .)"
|
||||
if ! [ "$(echo "$PGREP_OUTPUT" | wc -l)" -eq 2 ]; then
|
||||
echo "[WARN] Some processes might not have exited:"
|
||||
echo "$PGREP_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Exit cleanly
|
||||
echo "[INFO] Server stopped gracefully"
|
||||
exit 0
|
||||
else
|
||||
echo "[ERROR]: Can't find which screen to use"
|
||||
screen -ls
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Enable debug mode
|
||||
DEBUG="${DEBUG:-false}"
|
||||
if [ "$DEBUG" = "true" ]; then
|
||||
@ -32,8 +71,9 @@ while IFS='=' read -r ENVVAR VALUE ; do
|
||||
rm "${FILE}.bak"
|
||||
fi
|
||||
else
|
||||
[ "$DEBUG" = "true" ] && \
|
||||
if [ "$DEBUG" = "true" ]; then
|
||||
echo "[DEBUG] \"$ENVVAR\" doesn't have the prefix \"$PREFIX\""
|
||||
fi
|
||||
fi
|
||||
done < <(env)
|
||||
|
||||
@ -43,17 +83,33 @@ if [ "$DEBUG" = "true" ]; then
|
||||
cat "$FILE"
|
||||
fi
|
||||
|
||||
# Pre-create the screen log
|
||||
touch screenlog.0
|
||||
# Set up a SIGTERM signal trap to stop the server
|
||||
trap 'stop_server' SIGTERM
|
||||
|
||||
# Run server in screen (without attaching)
|
||||
echo "[INFO] Starting Minecraft server"
|
||||
/usr/bin/screen -dmS minecraft -L \
|
||||
bash -c "
|
||||
sleep 0.5
|
||||
[ $DEBUG = true ] && echo '[DEBUG] Starting server'
|
||||
/usr/bin/java $JVM_OPTS -jar server.jar --nogui
|
||||
"
|
||||
bash -c "/usr/bin/java $JVM_OPTS -jar server.jar --nogui"
|
||||
|
||||
# Tail screen log to container stdout
|
||||
[ "$DEBUG" = "true" ] && echo "[DEBUG] Tailing screenlog.0"
|
||||
tail -f screenlog.0
|
||||
# Get screen PID
|
||||
[ "$DEBUG" = "true" ] && screen -ls
|
||||
SCREEN_PID="$(
|
||||
screen -ls | grep -oE '[0-9]+\.minecraft' | cut -d. -f1
|
||||
)"
|
||||
|
||||
# Check screen PID
|
||||
if ! kill -0 "$SCREEN_PID" 2>/dev/null; then
|
||||
echo "[ERROR] Cannot find Minecraft screen (PID: \"$SCREEN_PID\")"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Output logs to stdout (touch in case slow to create)
|
||||
touch screenlog.0
|
||||
tail -f screenlog.0 &
|
||||
TAIL_PID="$!"
|
||||
|
||||
# Wait for screen to exit
|
||||
strace -e exit -e signal=none -p "$SCREEN_PID" 2>/dev/null &
|
||||
STRACE_PID="$!"
|
||||
[ "$DEBUG" = "true" ] && ps aux
|
||||
wait "$STRACE_PID"
|
||||
|
Loading…
Reference in New Issue
Block a user