diff options
Diffstat (limited to 'docker')
| -rw-r--r-- | docker/dedicated-server/Dockerfile | 33 | ||||
| -rw-r--r-- | docker/dedicated-server/entrypoint.sh | 91 |
2 files changed, 124 insertions, 0 deletions
diff --git a/docker/dedicated-server/Dockerfile b/docker/dedicated-server/Dockerfile new file mode 100644 index 00000000..14760afd --- /dev/null +++ b/docker/dedicated-server/Dockerfile @@ -0,0 +1,33 @@ +FROM debian:bookworm-slim + +ARG DEBIAN_FRONTEND=noninteractive +# basically, it only works with a Release build.(libs are not included in Debug build) +ARG MC_RUNTIME_DIR=x64/Minecraft.Server/Release + +RUN dpkg --add-architecture i386 \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + ca-certificates \ + wine \ + wine64 \ + wine32:i386 \ + xvfb \ + tini \ + && rm -rf /var/lib/apt/lists/* + +ENV WINEARCH=win64 +ENV WINEPREFIX=/var/opt/wineprefix64 + +WORKDIR /srv/mc + +COPY ${MC_RUNTIME_DIR}/Minecraft.Server.exe /srv/mc/Minecraft.Server.exe +COPY ${MC_RUNTIME_DIR}/iggy_w64.dll /srv/mc/iggy_w64.dll +COPY ${MC_RUNTIME_DIR}/Common /srv/mc/Common +COPY ${MC_RUNTIME_DIR}/Windows64 /srv/mc/Windows64 +COPY docker/dedicated-server/entrypoint.sh /usr/local/bin/entrypoint.sh + +RUN chmod 0755 /usr/local/bin/entrypoint.sh \ + && mkdir -p /var/opt/wineprefix64 /srv/mc \ + && test -f /srv/mc/Minecraft.Server.exe + +ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/entrypoint.sh"] diff --git a/docker/dedicated-server/entrypoint.sh b/docker/dedicated-server/entrypoint.sh new file mode 100644 index 00000000..a8f8907a --- /dev/null +++ b/docker/dedicated-server/entrypoint.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +set -euo pipefail + +SERVER_DIR="/srv/mc" +SERVER_EXE="Minecraft.Server.exe" +# ip & port are fixed since they run inside the container +SERVER_PORT="25565" +SERVER_BIND_IP="0.0.0.0" + +PERSIST_DIR="/srv/persist" +WINE_CMD="" + +ensure_persist_file() { + local persist_path="$1" + local runtime_path="$2" + local default_text="$3" + + if [ ! -f "${persist_path}" ]; then + if [ -f "${runtime_path}" ] && [ ! -L "${runtime_path}" ]; then + cp -f "${runtime_path}" "${persist_path}" + else + printf '%b' "${default_text}" > "${persist_path}" + fi + fi + + if [ -e "${runtime_path}" ] && [ ! -L "${runtime_path}" ]; then + rm -f "${runtime_path}" + fi + + ln -sfn "${persist_path}" "${runtime_path}" +} + +if [ ! -d "$SERVER_DIR" ]; then + echo "[error] Server directory not found: $SERVER_DIR" >&2 + exit 1 +fi + +cd "$SERVER_DIR" + +if [ ! -f "$SERVER_EXE" ]; then + echo "[error] ${SERVER_EXE} not found in ${SERVER_DIR}" >&2 + echo "[hint] Rebuild image with a valid MC_RUNTIME_DIR build arg that contains dedicated server runtime files." >&2 + exit 1 +fi + +mkdir -p "${PERSIST_DIR}" + +# created because it is not implemented on the server side +mkdir -p "${PERSIST_DIR}/GameHDD" + +ensure_persist_file "${PERSIST_DIR}/server.properties" "server.properties" "" +ensure_persist_file "${PERSIST_DIR}/banned-players.json" "banned-players.json" "[]\n" +ensure_persist_file "${PERSIST_DIR}/banned-ips.json" "banned-ips.json" "[]\n" + +# differs from the structure, but it’s reorganized into a more manageable structure to the host side +if [ -e "Windows64/GameHDD" ] && [ ! -L "Windows64/GameHDD" ]; then + rm -rf "Windows64/GameHDD" +fi +ln -sfn "${PERSIST_DIR}/GameHDD" "Windows64/GameHDD" + +# for compatibility with other images +if command -v wine64 >/dev/null 2>&1; then + WINE_CMD="wine64" +elif [ -x "/usr/lib/wine/wine64" ]; then + WINE_CMD="/usr/lib/wine/wine64" +elif command -v wine >/dev/null 2>&1; then + WINE_CMD="wine" +else + echo "[error] No Wine executable found (wine64/wine)." >&2 + exit 1 +fi + +if [ ! -d "${WINEPREFIX}" ] || [ -z "$(ls -A "${WINEPREFIX}" 2>/dev/null)" ]; then + mkdir -p "${WINEPREFIX}" +fi + +# in the current implementation, a virtual screen is required because the client-side logic is being called for compatibility +if [ -z "${DISPLAY:-}" ]; then + export DISPLAY="${XVFB_DISPLAY:-:99}" + XVFB_SCREEN="${XVFB_SCREEN:-64x64x16}" + Xvfb "${DISPLAY}" -nolisten tcp -screen 0 "${XVFB_SCREEN}" >/tmp/xvfb.log 2>&1 & + sleep 0.2 +fi + +args=( + -port "${SERVER_PORT}" + -bind "${SERVER_BIND_IP}" +) + +echo "[info] Starting ${SERVER_EXE} on ${SERVER_BIND_IP}:${SERVER_PORT}" +exec "${WINE_CMD}" "${SERVER_EXE}" "${args[@]}" |
