From 99159293407118c58c5f89c2ab7fb5ed63533842 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Sat, 6 Mar 2021 16:53:46 -0600 Subject: [PATCH 01/27] ci: Added java15-openj9 --- .github/workflows/build-multiarch.yml | 1 + docker-versions-create.sh | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-multiarch.yml b/.github/workflows/build-multiarch.yml index f5ee8f6c..76307c28 100644 --- a/.github/workflows/build-multiarch.yml +++ b/.github/workflows/build-multiarch.yml @@ -6,6 +6,7 @@ on: - java8-multiarch - multiarch-latest - java15 + - java15-openj9 - test/multiarch/* tags: - "[0-9]+.[0-9]+.[0-9]+-multiarch" diff --git a/docker-versions-create.sh b/docker-versions-create.sh index 93c4a9d6..59b5ee34 100755 --- a/docker-versions-create.sh +++ b/docker-versions-create.sh @@ -1,7 +1,17 @@ #!/bin/bash #set -x # Use this variable to indicate a list of branches that docker hub is watching -branches_list=('java8' 'java8-multiarch' 'openj9' 'openj9-11' 'adopt11' 'java15' 'multiarch' 'multiarch-latest') +branches_list=( + 'java8' + 'java8-multiarch' + 'openj9' + 'openj9-11' + 'adopt11' + 'java15' + 'java15-openj9' + 'multiarch' + 'multiarch-latest' + ) function TrapExit { echo "Checking out back in master" From 6e2b3ae0c7e8b6635a3bb42c6450fab7782b4496 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Sat, 6 Mar 2021 17:26:08 -0600 Subject: [PATCH 02/27] docs: Added java15-openj9 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3a0adec9..a17d5035 100644 --- a/README.md +++ b/README.md @@ -166,6 +166,7 @@ To use a different version of Java, please use a docker tag to run your Minecraf | java8 | 8 | Alpine | Hotspot | amd64 | | java8-multiarch | 8 | Debian | Hotspot | amd64,arm64,armv7 | | java15 | 15 | Debian | Hotspot | amd64,arm64,armv7 | +| java15-openj9 | 15 | Debian | OpenJ9 | amd64,arm64 | | adopt11 | 11 | Alpine | Hotspot | amd64 | | openj9 | 8 | Alpine | OpenJ9 | amd64 | | openj9-11 | 11 | Alpine | OpenJ9 | amd64 | From 6c6bf030c5f5ee19f3ebafcf790689b2493163aa Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Sun, 7 Mar 2021 13:06:45 -0600 Subject: [PATCH 03/27] docs: Added troubleshooting info for rpi #795 --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a17d5035..ff182338 100644 --- a/README.md +++ b/README.md @@ -1196,8 +1196,10 @@ When the container is signalled to stop, the Minecraft process wrapper will atte ## Running on RaspberryPi -To run this image on a RaspberryPi 3 B+, 4, or newer, use the image tag +To run this image on a RaspberryPi 3 B+, 4, or newer, use any of the image tags [list in the Java version section](#running-minecraft-server-on-different-java-version) that specify `armv7` for the architecture, such as itzg/minecraft-server:multiarch > NOTE: you may need to lower the memory allocation, such as `-e MEMORY=750m` + +> If experiencing issues such as "sleep: cannot read realtime clock: Operation not permitted", ensure `libseccomp` is up to date on your host. In some cases adding `:Z` flag to the `/data` mount may be needed, [but use cautiously](https://docs.docker.com/storage/bind-mounts/#configure-the-selinux-label). From d3bd697cb2fad480779c29f92ce382a2bb90d4e3 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Tue, 9 Mar 2021 22:05:21 -0600 Subject: [PATCH 04/27] Fixed warning reported when no paper jars to remove --- start-deployPaper | 1 + 1 file changed, 1 insertion(+) diff --git a/start-deployPaper b/start-deployPaper index 6058be2b..1427bb7e 100644 --- a/start-deployPaper +++ b/start-deployPaper @@ -57,6 +57,7 @@ else fi log "Removing old PaperMC versions ..." + shopt -s nullglob for f in paper-*.jar; do [[ $f != $SERVER ]] && rm $f done From cd3ea7fd2e4cbb7851dcb33108738facaf3ef0ca Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Tue, 9 Mar 2021 22:13:33 -0600 Subject: [PATCH 05/27] Upgraded mc-monitor to 0.7.0 #795 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c6d9c63c..366c5063 100644 --- a/Dockerfile +++ b/Dockerfile @@ -51,7 +51,7 @@ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \ --from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \ - --var version=0.1.7 --var app=mc-monitor --file {{.app}} \ + --var version=0.7.0 --var app=mc-monitor --file {{.app}} \ --from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \ From 6fa827e9a11f1d6c59ce4b40af2857b7a775f8cb Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Thu, 11 Mar 2021 15:08:26 -0600 Subject: [PATCH 06/27] Fixed usage of EXTRA_ARGS #798 --- start-minecraftFinalSetup | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/start-minecraftFinalSetup b/start-minecraftFinalSetup index 268a6698..40c1358c 100644 --- a/start-minecraftFinalSetup +++ b/start-minecraftFinalSetup @@ -61,15 +61,14 @@ for j in $JSON_FILES; do fi done -EXTRA_ARGS="" # Optional disable console if versionLessThan 1.14 && [[ ${CONSOLE,,} = false ]]; then - EXTRA_ARGS+="--noconsole" + EXTRA_ARGS+=" --noconsole" fi # Optional disable GUI for headless servers if [[ ${GUI} = false || ${GUI} = FALSE ]]; then - EXTRA_ARGS="${EXTRA_ARGS} nogui" + EXTRA_ARGS+=" nogui" fi # put these prior JVM_OPTS at the end to give any memory settings there higher precedence From 209c6e6dabf59772039f2fa3c1b0c61379668ef9 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Thu, 11 Mar 2021 15:36:34 -0600 Subject: [PATCH 07/27] Added explicit -dir for Fabric installer #797 --- start-deployFabric | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/start-deployFabric b/start-deployFabric index e933b6f7..4734e0ea 100644 --- a/start-deployFabric +++ b/start-deployFabric @@ -54,7 +54,10 @@ if [[ ! -e $installMarker ]]; then tries=3 set +e while ((--tries >= 0)); do - java -jar $FABRIC_INSTALLER server -mcversion $VANILLA_VERSION -downloadMinecraft + java -jar $FABRIC_INSTALLER server \ + -mcversion $VANILLA_VERSION \ + -downloadMinecraft \ + -dir /data if [[ $? == 0 ]]; then break fi From 3c77abbbab2df9c86d24a542321434e9fd909046 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Thu, 11 Mar 2021 16:21:59 -0600 Subject: [PATCH 08/27] Added debug output for deployForge and minecraftFinalSetup #799 --- start-deployForge | 1 + start-minecraftFinalSetup | 1 + 2 files changed, 2 insertions(+) diff --git a/start-deployForge b/start-deployForge index f6b273eb..c7f14e6d 100644 --- a/start-deployForge +++ b/start-deployForge @@ -3,6 +3,7 @@ . ${SCRIPTS:-/}start-utils export TYPE=FORGE : ${FORGEVERSION:=RECOMMENDED} +isDebugging && set -x if [[ -z $FORGE_INSTALLER && -z $FORGE_INSTALLER_URL ]]; then norm=$VANILLA_VERSION diff --git a/start-minecraftFinalSetup b/start-minecraftFinalSetup index 40c1358c..fc3cfa1d 100644 --- a/start-minecraftFinalSetup +++ b/start-minecraftFinalSetup @@ -1,6 +1,7 @@ #!/bin/bash . ${SCRIPTS:-/}start-utils +isDebugging && set -x if [ -n "$OPS" ]; then log "Updating ops" From 44138564b0a4590c8dbde767c8d1df53d1153cc0 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Thu, 11 Mar 2021 16:29:21 -0600 Subject: [PATCH 09/27] Added debug output for deployCustom #799 --- start-deployCustom | 1 + 1 file changed, 1 insertion(+) diff --git a/start-deployCustom b/start-deployCustom index e2939ab8..156ee9ba 100644 --- a/start-deployCustom +++ b/start-deployCustom @@ -1,6 +1,7 @@ #!/bin/bash . ${SCRIPTS:-/}start-utils +isDebugging && set -x if isURL ${CUSTOM_SERVER}; then filename=$(basename ${CUSTOM_SERVER}) From e659343821540f0f57802cd6c53fd847dd4657e8 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Thu, 11 Mar 2021 19:40:11 -0600 Subject: [PATCH 10/27] Improved locating of forge server jar created by installer #799 --- start-deployForge | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/start-deployForge b/start-deployForge index c7f14e6d..089782f6 100644 --- a/start-deployForge +++ b/start-deployForge @@ -46,6 +46,8 @@ elif [[ -z $FORGE_INSTALLER ]]; then elif [[ ! -e $FORGE_INSTALLER ]]; then log "ERROR: the given Forge installer doesn't exist : $FORGE_INSTALLER" exit 2 +else + shortForgeVersion=$VANILLA_VERSION-custom fi installMarker="/data/.forge-installed-$shortForgeVersion" @@ -98,7 +100,11 @@ if [ ! -e $installMarker ]; then log "Finding installed server jar..." unset -v latest for file in *forge*.jar; do - [[ $file =~ installer ]] || [[ $file -nt $latest ]] && latest=$file + if ! [[ $file =~ installer ]]; then + if [[ -z $latest ]] || [[ $file -nt $latest ]]; then + latest=$file + fi + fi done if [[ -z $latest ]]; then log "Unable to derive server jar for Forge" From 46bfbaada14ca8af07aef77ece434062142e12a4 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Fri, 12 Mar 2021 09:27:44 -0600 Subject: [PATCH 11/27] Upgraded mc-monitor to 0.7.1 to fix ProtocolSupport response #796 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 366c5063..5f20af35 100644 --- a/Dockerfile +++ b/Dockerfile @@ -51,7 +51,7 @@ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \ --from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \ - --var version=0.7.0 --var app=mc-monitor --file {{.app}} \ + --var version=0.7.1 --var app=mc-monitor --file {{.app}} \ --from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \ From 2bdaa4dc4edcf8675b1e9d495da39555ac1d7ddd Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Fri, 12 Mar 2021 17:22:54 -0600 Subject: [PATCH 12/27] Updated java8 warning message for ClassCastException #775 --- start-configuration | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/start-configuration b/start-configuration index 720e0fb7..1a689a1b 100644 --- a/start-configuration +++ b/start-configuration @@ -108,6 +108,8 @@ case "${TYPE^^}" in log "**********************************************************************" log "WARNING: The image tag itzg/minecraft-server:java8 is recommended" log " since some mods require Java 8" + log " Exception traces reporting ClassCastException: class jdk.internal.loader.ClassLoaders\$AppClassLoader" + log " can be fixed with java8" log "**********************************************************************" exec ${SCRIPTS:-/}start-deployForge "$@" ;; @@ -120,6 +122,8 @@ case "${TYPE^^}" in log "**********************************************************************" log "WARNING: The image tag itzg/minecraft-server:java8 is recommended" log " since some mods require Java 8" + log " Exception traces reporting ClassCastException: class jdk.internal.loader.ClassLoaders\$AppClassLoader" + log " can be fixed with java8" log "**********************************************************************" exec ${SCRIPTS:-/}start-deployCF "$@" ;; From d022956e240d29dd65d3ef77ba2134b4a847d598 Mon Sep 17 00:00:00 2001 From: miki164 <32245772+miki164@users.noreply.github.com> Date: Sat, 13 Mar 2021 13:52:14 +0100 Subject: [PATCH 13/27] Fix typo in example docker-compose (#803) --- examples/docker-compose-simple.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/docker-compose-simple.yml b/examples/docker-compose-simple.yml index afb7a35f..f9b0ba40 100644 --- a/examples/docker-compose-simple.yml +++ b/examples/docker-compose-simple.yml @@ -9,4 +9,4 @@ services: EULA: "TRUE" volumes: # attach the relative directory 'data' to the container's /data path - ./data:/data + - ./data:/data From 8d1989a595d4edaf802cf4dfc293219977c60733 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Sat, 13 Mar 2021 16:54:56 -0600 Subject: [PATCH 14/27] docs: Added more info about getbukkit's weird 1.8 file naming #103 --- README.md | 2 ++ start-deployBukkitSpigot | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ff182338..c9ddb7b5 100644 --- a/README.md +++ b/README.md @@ -460,6 +460,8 @@ You can build spigot from source by adding `-e BUILD_FROM_SOURCE=true` If you have attached a host directory to the `/data` volume, then you can install plugins within the `plugins` subdirectory. You can also [attach a `/plugins` volume](#deploying-plugins-from-attached-volume). If you add plugins while the container is running, you'll need to restart it to pick those up. +> NOTE some of the `VERSION` values are not as intuitive as you would think, so make sure to click into the version entry to find the **exact** version needed for the download. For example, "1.8" is not sufficient since their download naming expects `1.8-R0.1-SNAPSHOT-latest` exactly. + ## Running a Paper server Enable Paper server mode by adding a `-e TYPE=PAPER` to your command-line. diff --git a/start-deployBukkitSpigot b/start-deployBukkitSpigot index 37b59269..023d87b2 100644 --- a/start-deployBukkitSpigot +++ b/start-deployBukkitSpigot @@ -82,7 +82,9 @@ function downloadSpigot { ERROR: failed to download from $downloadUrl Visit https://getbukkit.org/download/${getbukkitFlavor} to lookup the - exact version, such as 1.4.6-R0.4-SNAPSHOT or 1.8-R0.1-SNAPSHOT-LATEST + exact version, such as 1.4.6-R0.4-SNAPSHOT or 1.8-R0.1-SNAPSHOT-latest. + Click into the version entry to find the **exact** version, because something + like "1.8" is not sufficient according to their download naming. EOF From 28810fcba3e85415b4beca42a908238ee3a3eb3d Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Sun, 14 Mar 2021 15:02:40 -0500 Subject: [PATCH 15/27] Added support for CF modpacks using settings.cfg #772 #800 --- start-deployCF | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/start-deployCF b/start-deployCF index 86bd44ca..a881e7bc 100644 --- a/start-deployCF +++ b/start-deployCF @@ -3,6 +3,24 @@ set -e . ${SCRIPTS:-/}start-utils + +loadForgeVars() { + cfgFile=${1?} + pat='^([^#;][^=]+)=[:space:]*([^;]*)' + while read -r line || [[ -n "$line" ]] ; do + if [[ $line =~ $pat ]]; then + #echo "MATCHED $line" + k=${BASH_REMATCH[1]} + v=${BASH_REMATCH[2]} + case $k in + FORGEURL) + forgeInstallerUrl="$v" + ;; + esac + fi + done < "$cfgFile" +} + isDebugging && set -x : ${FTB_BASE_DIR:=${CF_BASE_DIR:-/data/FeedTheBeast}} @@ -44,9 +62,24 @@ if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then serverJar=$(find ${FTB_BASE_DIR} -path "*/libraries/*" -prune -type f -o -not -name "forge*installer.jar" -name "forge*.jar") if [[ -z "$serverJar" ]]; then - forgeInstallerJar=$(find ${FTB_BASE_DIR} -name "forge*installer.jar") + + if [ -f "${FTB_BASE_DIR}/settings.cfg" ]; then + loadForgeVars "${FTB_BASE_DIR}/settings.cfg" + + if [[ $forgeInstallerUrl ]]; then + forgeInstallerJar="${FTB_BASE_DIR}/forge-installer.jar" + if ! curl -fsSL -o "$forgeInstallerJar" "$forgeInstallerUrl" ; then + log "ERROR failed to download Forge installer from $forgeInstallerUrl" + exit 2 + fi + fi + else + forgeInstallerJar=$(find ${FTB_BASE_DIR} -name "forge*installer.jar") + fi + if [[ -z "${forgeInstallerJar}" ]]; then - log "ERROR Unable to find forge installer in modpack." + log "ERROR Unable to find forge installer in modpack" + log " or download using modpack config." log " Make sure you downloaded the server files." exit 2 fi From c4b573f608b8fc275ef541fec04dac46864fb564 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Sun, 14 Mar 2021 16:18:43 -0500 Subject: [PATCH 16/27] docs: Clarified disabling of max tick watchdog for autopause #555 --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c9ddb7b5..0d20a9f6 100644 --- a/README.md +++ b/README.md @@ -217,7 +217,9 @@ An autopause functionality has been added to this image to monitor whether clien Of course, even loaded chunks are not ticked when the process is stopped. -From the server's point of view, the pausing causes a single tick to take as long as the process is stopped, so the server watchdog might intervene after the process is continued, possibly forcing a container restart. To prevent this, ensure that the `max-tick-time` in the `server.properties` file is set correctly. Non-vanilla versions might have their own configuration file, you might have to disable their watchdogs separately (e.g. PAPER Servers). +**You must greatly increase or disable max-tick-time watchdog functionality.** From the server's point of view, the pausing causes a single tick to take as long as the process is stopped, so the server watchdog might intervene after the process is continued, possibly forcing a container restart. To prevent this, ensure that the `max-tick-time` in the `server.properties` file is set to a very large value or -1 to disable it entirely, which is highly recommended. That can be set with `MAX_TICK_TIME` as described in [the section below](#max-tick-time). + +> **NOTE:** Non-vanilla versions might have their own configuration file, you might have to disable their watchdogs separately (e.g. PAPER Servers). On startup the `server.properties` file is checked and, if applicable, a warning is printed to the terminal. When the server is created (no data available in the persistent directory), the properties file is created with the Watchdog disabled. From c31b191b9634b9a0cd0fba52f68150313846f6ee Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Thu, 18 Mar 2021 19:56:40 -0500 Subject: [PATCH 17/27] Removed "dot output" when running forge installer for CF modpacks #800 --- start-deployCF | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/start-deployCF b/start-deployCF index a881e7bc..ecff5e0a 100644 --- a/start-deployCF +++ b/start-deployCF @@ -74,7 +74,7 @@ if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then fi fi else - forgeInstallerJar=$(find ${FTB_BASE_DIR} -name "forge*installer.jar") + forgeInstallerJar=$(find "${FTB_BASE_DIR}" -name "forge*installer.jar") fi if [[ -z "${forgeInstallerJar}" ]]; then @@ -85,7 +85,7 @@ if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then fi log "Installing forge server" - (cd $(dirname "${forgeInstallerJar}"); java -jar $(basename "${forgeInstallerJar}") --installServer) | awk '{printf "."} END {print ""}' + (cd $(dirname "${forgeInstallerJar}"); java -jar $(basename "${forgeInstallerJar}") --installServer) fi echo "${FTB_SERVER_MOD}" > $installMarker From a2132292ac90ae49f5a64a19106cd8bc7e83f877 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Thu, 18 Mar 2021 20:00:30 -0500 Subject: [PATCH 18/27] Separated OVERRIDE_OPS|WHITELIST from OPS|WHITELIST logic #806 --- start-minecraftFinalSetup | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/start-minecraftFinalSetup b/start-minecraftFinalSetup index fc3cfa1d..36b349a9 100644 --- a/start-minecraftFinalSetup +++ b/start-minecraftFinalSetup @@ -7,22 +7,20 @@ if [ -n "$OPS" ]; then log "Updating ops" rm -f /data/ops.txt.converted echo $OPS | awk -v RS=, '{print}' > /data/ops.txt - - if isTrue "${OVERRIDE_OPS}"; then - log "Recreating ops.json file at server startup" - rm -f /data/ops.json - fi +fi +if isTrue "${OVERRIDE_OPS}"; then + log "Recreating ops.json file at server startup" + rm -f /data/ops.json fi if [ -n "$WHITELIST" ]; then log "Updating whitelist" rm -f /data/white-list.txt.converted echo $WHITELIST | awk -v RS=, '{print}' > /data/white-list.txt - - if isTrue "${OVERRIDE_WHITELIST}"; then - log "Recreating whitelist.json file at server startup" - rm -f /data/whitelist.json - fi +fi +if isTrue "${OVERRIDE_WHITELIST}"; then + log "Recreating whitelist.json file at server startup" + rm -f /data/whitelist.json fi if [ -n "$ICON" ]; then From d695fc3fbcbf8d44291c75bfae6e245ae133d76d Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Sun, 21 Mar 2021 10:12:35 -0500 Subject: [PATCH 19/27] Disable whitelist server property when WHITELIST empty and overriding #806 --- start-finalSetupServerProperties | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/start-finalSetupServerProperties b/start-finalSetupServerProperties index a4c7c62c..62e02dfd 100644 --- a/start-finalSetupServerProperties +++ b/start-finalSetupServerProperties @@ -31,6 +31,10 @@ function customizeServerProps { log "Creating whitelist" setServerProp "whitelist" "true" setServerProp "white-list" "true" + else + log "Disabling whitelist" + setServerProp "whitelist" "false" + setServerProp "white-list" "false" fi # If not provided, generate a reasonable default message-of-the-day, From 5225ba06c8c0d0e441c364d489bdccd9b203bb6d Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Sun, 21 Mar 2021 11:43:21 -0500 Subject: [PATCH 20/27] Added support for spiget to download Spigot/Bukkit/Paper plugins #808 --- README.md | 17 ++++++++++++ start-deployBukkitSpigot | 3 +-- start-deployPaper | 3 +-- start-spiget | 58 ++++++++++++++++++++++++++++++++++++++++ start-utils | 9 ++++++- 5 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 start-spiget diff --git a/README.md b/README.md index 0d20a9f6..0353f811 100644 --- a/README.md +++ b/README.md @@ -462,6 +462,8 @@ You can build spigot from source by adding `-e BUILD_FROM_SOURCE=true` If you have attached a host directory to the `/data` volume, then you can install plugins within the `plugins` subdirectory. You can also [attach a `/plugins` volume](#deploying-plugins-from-attached-volume). If you add plugins while the container is running, you'll need to restart it to pick those up. +[You can also auto-download plugins using `SPIGET_RESOURCES`.](#auto-downloading-spigotmcbukkitpapermc-plugins) + > NOTE some of the `VERSION` values are not as intuitive as you would think, so make sure to click into the version entry to find the **exact** version needed for the download. For example, "1.8" is not sufficient since their download naming expects `1.8-R0.1-SNAPSHOT-latest` exactly. ## Running a Paper server @@ -484,6 +486,8 @@ An example compose file is provided at If you have attached a host directory to the `/data` volume, then you can install plugins via the `plugins` subdirectory. You can also [attach a `/plugins` volume](#deploying-plugins-from-attached-volume). If you add plugins while the container is running, you'll need to restart it to pick those up. +[You can also auto-download plugins using `SPIGET_RESOURCES`.](#auto-downloading-spigotmcbukkitpapermc-plugins) + ## Running a Tuinity server A [Tuinity](https://github.com/Spottedleaf/Tuinity) server, which is a fork of Paper aimed at improving server performance at high playercounts. @@ -705,6 +709,19 @@ There is one additional volume that can be mounted; `/plugins`. Any files in thi This works well if you want to have a common set of plugins in a separate location, but still have multiple worlds with different server requirements in either persistent volumes or a downloadable archive. +## Auto-downloading SpigotMC/Bukkit/PaperMC plugins + +The `SPIGET_RESOURCES` variable can be set with a comma-separated list of SpigotMC resource IDs to automatically download [SpigotMC resources/plugins](https://www.spigotmc.org/resources/) using [the spiget API](https://spiget.org/). Resources that are zip files will be expanded into the plugins directory and resources that are simply jar files will be moved there. + +The **resource ID** can be located from the numerical part of the URL after the shortname and a dot. For example, the ID is **9089** from + + https://www.spigotmc.org/resources/essentialsx.9089/ + ==== + +For example, the following will auto-download the [EssentialsX](https://www.spigotmc.org/resources/essentialsx.9089/) and [Vault](https://www.spigotmc.org/resources/vault.34315/) plugins: + + -e SPIGET_RESOURCES=9089,34315 + ## Running with a custom server JAR If you would like to run a custom server JAR, set `-e TYPE=CUSTOM` and pass the custom server diff --git a/start-deployBukkitSpigot b/start-deployBukkitSpigot index 023d87b2..0047730d 100644 --- a/start-deployBukkitSpigot +++ b/start-deployBukkitSpigot @@ -125,5 +125,4 @@ fi export TYPE=SPIGOT export SKIP_LOG4J_CONFIG=true -# Continue to Final Setup -exec ${SCRIPTS:-/}start-finalSetupWorld $@ +exec ${SCRIPTS:-/}start-spiget "$@" diff --git a/start-deployPaper b/start-deployPaper index 1427bb7e..e221eb58 100644 --- a/start-deployPaper +++ b/start-deployPaper @@ -76,5 +76,4 @@ fi export TYPE=SPIGOT export SKIP_LOG4J_CONFIG=true -# Continue to Final Setup -exec ${SCRIPTS:-/}start-finalSetupWorld "$@" +exec ${SCRIPTS:-/}start-spiget "$@" diff --git a/start-spiget b/start-spiget new file mode 100644 index 00000000..c3ca5f41 --- /dev/null +++ b/start-spiget @@ -0,0 +1,58 @@ +#!/bin/bash +set -euo pipefail +IFS=$'\n\t' + +. ${SCRIPTS:-/}start-utils +handleDebugMode + +: ${SPIGET_RESOURCES:=} + +containsJars() { + file=${1?} + + pat='\.jar$' + + while read -r line; do + if [[ $line =~ $pat ]]; then + return 0 + fi + done <<< $(unzip -l "$file") + + return 1 +} + +getResourceFromSpiget() { + resource=${1?} + + log "Downloading resource ${resource} ..." + + tmpfile="/tmp/${resource}.zip" + url="https://api.spiget.org/v2/resources/${resource}/download" + if ! curl -o "${tmpfile}" -fsSL -H "User-Agent: itzg/minecraft-server" "${extraCurlArgs[@]}" "${url}"; then + log "ERROR failed to download resource '${resource}' from ${url}" + exit 2 + fi + + mkdir -p /data/plugins + if containsJars "${tmpfile}"; then + log "Extracting contents of resource ${resource} into plugins" + unzip -o -q -d /data/plugins "${tmpfile}" + rm "${tmpfile}" + else + log "Moving resource ${resource} into plugins" + mv "${tmpfile}" "/data/plugins/${resource}.jar" + fi + +} + +if [[ ${SPIGET_RESOURCES} ]]; then + log "Getting plugins via Spiget" + IFS=',' read -r -a resources <<< "${SPIGET_RESOURCES}" + for resource in "${resources[@]}" + do + getResourceFromSpiget "${resource}" + done +fi + +# Continue to Final Setup +exec ${SCRIPTS:-/}start-finalSetupWorld $@ diff --git a/start-utils b/start-utils index 51c70d64..05f569ce 100644 --- a/start-utils +++ b/start-utils @@ -57,13 +57,20 @@ function isTrue() { } function isDebugging() { - if [[ -v DEBUG ]] && [[ ${DEBUG^^} == TRUE ]]; then + if isTrue "${DEBUG:-false}"; then return 0 else return 1 fi } +function handleDebugMode() { + if isDebugging; then + set -x + extraCurlArgs=(-v) + fi +} + function debug() { if isDebugging; then log "DEBUG: $*" From 8049bd5b8038337efb691989a1cf775dbcb56b1a Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Sun, 21 Mar 2021 15:35:12 -0500 Subject: [PATCH 21/27] docs: Lots of cleanup about /data path and management of mods and plugins related to that --- README.md | 367 +++++++++++++++------------------ docs/level-vs-world.drawio.png | Bin 0 -> 34180 bytes 2 files changed, 168 insertions(+), 199 deletions(-) create mode 100644 docs/level-vs-world.drawio.png diff --git a/README.md b/README.md index 0353f811..9a3ebecf 100644 --- a/README.md +++ b/README.md @@ -109,16 +109,23 @@ such as: docker run -d -it -v /etc/timezone:/etc/timezone:ro -p 25565:25565 --name mc itzg/minecraft-server -## Attaching data directory to host filesystem +## Data Directory -In order to readily access the Minecraft data, use the `-v` argument -to map a directory on your host machine to the container's `/data` directory, such as: +Everything the container manages is located under the **container's** `/data` path, as shown here: - docker run -d -v /path/on/host:/data ... +![](docs/level-vs-world.drawio.png) -When attached in this way you can stop the server, edit the configuration under your attached `/path/on/host` and start the server again with `docker start CONTAINER_ID` to pick up the new configuration. +> NOTE: The container path `/data` is pre-declared as a volume, so if you do nothing then it will be allocated as an anonymous volume. As such, it is subject to removal when the container is removed. -As example, using Docker compose, create the following `docker-compose.yml` in its own directory and the container will automatically create/attach the relative directory `data` to the container: +### Attaching data directory to host filesystem + +In most cases the easier way to persist and work with the minecraft data files is to use the `-v` argument to map a directory on your host machine to the container's `/data` directory, such as the following where `/home/user/minecraft-data` would be a directory of your choosing on your host machine: + + docker run -d -v /home/user/minecraft-data:/data ... + +When attached in this way you can stop the server, edit the configuration under your attached directory and start the server again to pick up the new configuration. + +With Docker Compose, setting up a host attached directory is even easier since relative paths can be configured. For example, with the following `docker-compose.yml` Docker will automatically create/attach the relative directory `minecraft-data` to the container. ```yaml version: "3" @@ -131,8 +138,8 @@ services: environment: EULA: "TRUE" volumes: - # attach the relative directory 'data' to the container's /data path - - ./data:/data + # attach a directory relative to the directory containing this compose file + - ./minecraft-data:/data ``` ## Versions @@ -207,46 +214,6 @@ healthy Some orchestration systems, such as Portainer, don't allow for disabling the default `HEALTHCHECK` declared by this image. In those cases you can approximate the disabling of healthchecks by setting the environment variable `DISABLE_HEALTHCHECK` to `true`. -## Autopause - -### Description - -There are various bug reports on [Mojang](https://bugs.mojang.com) about high CPU usage of servers with newer versions, even with few or no clients connected (e.g. [this one](https://bugs.mojang.com/browse/MC-149018), in fact the functionality is based on [this comment in the thread](https://bugs.mojang.com/browse/MC-149018?focusedCommentId=593606&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-593606)). - -An autopause functionality has been added to this image to monitor whether clients are connected to the server. If for a specified time no client is connected, the Java process is stopped. When knocking on the server port (e.g. by the ingame Multiplayer server overview), the process is resumed. The experience for the client does not change. - -Of course, even loaded chunks are not ticked when the process is stopped. - -**You must greatly increase or disable max-tick-time watchdog functionality.** From the server's point of view, the pausing causes a single tick to take as long as the process is stopped, so the server watchdog might intervene after the process is continued, possibly forcing a container restart. To prevent this, ensure that the `max-tick-time` in the `server.properties` file is set to a very large value or -1 to disable it entirely, which is highly recommended. That can be set with `MAX_TICK_TIME` as described in [the section below](#max-tick-time). - -> **NOTE:** Non-vanilla versions might have their own configuration file, you might have to disable their watchdogs separately (e.g. PAPER Servers). - -On startup the `server.properties` file is checked and, if applicable, a warning is printed to the terminal. When the server is created (no data available in the persistent directory), the properties file is created with the Watchdog disabled. - -The utility used to wake the server (`knock(d)`) works at network interface level. So the correct interface has to be set using the `AUTOPAUSE_KNOCK_INTERFACE` variable when using non-default networking environments (e.g. host-networking, Portainer oder NAS solutions). See the description of the variable below. - -A starting, example compose file has been provided in [examples/docker-compose-autopause.yml](examples/docker-compose-autopause.yml). - -### Enabling Autopause - -Enable the Autopause functionality by setting: - -``` --e ENABLE_AUTOPAUSE=TRUE -``` - -The following environment variables define the behaviour of auto-pausing: -* `AUTOPAUSE_TIMEOUT_EST`, default `3600` (seconds) -describes the time between the last client disconnect and the pausing of the process (read as timeout established) -* `AUTOPAUSE_TIMEOUT_INIT`, default `600` (seconds) -describes the time between server start and the pausing of the process, when no client connects inbetween (read as timeout initialized) -* `AUTOPAUSE_TIMEOUT_KN`, default `120` (seconds) -describes the time between knocking of the port (e.g. by the main menu ping) and the pausing of the process, when no client connects inbetween (read as timeout knocked) -* `AUTOPAUSE_PERIOD`, default `10` (seconds) -describes period of the daemonized state machine, that handles the pausing of the process (resuming is done independently) -* `AUTOPAUSE_KNOCK_INTERFACE`, default `eth0` -
Describes the interface passed to the `knockd` daemon. If the default interface does not work, run the `ifconfig` command inside the container and derive the interface receiving the incoming connection from its output. The passed interface must exist inside the container. Using the loopback interface (`lo`) does likely not yield the desired results. - ## Deployment Templates and Examples ### Helm Charts @@ -287,163 +254,23 @@ the URL with `FORGE_INSTALLER_URL`, such as: In both of the cases above, there is no need for the `VERSION` or `FORGEVERSION` variables. -In order to add mods, you have two options. +### Managing mods -### Using the /data volume +In order to manage mods, you have two options: -This is the easiest way if you are using a persistent `/data` mount. +1. [Attach a host directory to the /data path](#attaching-data-directory-to-host-filesystem) and manage the contents of the `mods` subdirectory -To do this, you will need to attach the container's `/data` directory -(see "Attaching data directory to host filesystem”). -Then, you can add mods to the `/path/on/host/mods` folder you chose. From the example above, -the `/path/on/host` folder contents look like: +2. Using a mods-mount -``` -/path/on/host -├── mods -│   └── ... INSTALL MODS HERE ... -├── config -│   └── ... CONFIGURE MODS HERE ... -├── ops.json -├── server.properties -├── whitelist.json -├── worlds -│   └── ... PLACE MAPS IN THEIR OWN FOLDERS HERE ... -└── ... -``` +If the container paths `/mods` and/or `/config` exist, such as by attaching a docker volume or host path, then any files in either of these directories will be copied over to the respective `/data` subdirectory before starting Minecraft. -Providing a presistent `/data` mount is a good idea, both to persist the game world and to allow for the manual configuration which is sometimes needed. +If you want old mods to be removed as the `/mods` content is updated, then add `-e REMOVE_OLD_MODS=TRUE`. You can fine tune the removal process by specifying the `REMOVE_OLD_MODS_INCLUDE` and `REMOVE_OLD_MODS_EXCLUDE` variables. By default, everything will be removed. You can also specify the `REMOVE_OLD_MODS_DEPTH` (default is 16) variable to only delete files up to a certain level. -For instance, imagine a scenario when the initial launch has completed, but you now want to change the worldmap for your server. +For example: `-e REMOVE_OLD_MODS=TRUE -e REMOVE_OLD_MODS_INCLUDE="*.jar" -e REMOVE_OLD_MODS_DEPTH=1` will remove all old jar files that are directly inside the `plugins/` or `mods/` directory. -Assuming you have a shared directory to your container, you can then (after first launch) drag and drop your premade maps or worlds into the `\worlds\` directory. **Note:** each world should be placed in its own folder under the `\worlds\` directory. +You can specify the destination of the files that are copied from `/config` by setting the `COPY_CONFIG_DEST` variable, where the default is `/data/config`. For example, `-v ./config:/config -e COPY_CONFIG_DEST=/data` will allow you to copy over files like `bukkit.yml` and so on directly into the server directory. -Once your maps are in the proper path, you can then specify which map the server uses by changing the `level-name` value in `server.properties` to match the name of your map. - -If you add mods or make changes to `server.properties` while the container is running, you'll need to restart it to pick those -up: - - docker stop mc - docker start mc - -### Using separate mounts - -This is the easiest way if you are using an ephemeral `/data` filesystem, -or downloading a world with the `WORLD` option. - -There are two additional volumes that can be mounted; `/mods` and `/config`. -Any files in either of these filesystems will be copied over to the main -`/data` filesystem before starting Minecraft. If you want old mods to be removed as the `/mods` content is updated, then add `-e REMOVE_OLD_MODS=TRUE`. If you are running a `BUKKIT` distribution this will affect all files inside the `plugins/` directory. You can fine tune the removal process by specifing the `REMOVE_OLD_MODS_INCLUDE` and `REMOVE_OLD_MODS_EXCLUDE` variables. By default everything will be removed. You can also specify the `REMOVE_OLD_MODS_DEPTH` (default 16) variable to only delete files up to a certain level. - -> For example: `-e REMOVE_OLD_MODS=TRUE -e REMOVE_OLD_MODS_INCLUDE="*.jar" -e REMOVE_OLD_MODS_DEPTH=1` will remove all old jar files that are directly inside the `plugins/` or `mods/` directory. - -This works well if you want to have a common set of modules in a separate -location, but still have multiple worlds with different server requirements -in either persistent volumes or a downloadable archive. - -You can specify the destination of the configs that are located inside the `/config` mount by setting the `COPY_CONFIG_DEST` variable. The configs are copied recursivly to the `/data/config` directory by default. If a file was updated directly inside the `/data/*` directoy and is newer than the file in the `/config/*` mount it will not be overriden. - -> For example: `-v ./config:/config -e COPY_CONFIG_DEST=/data` will allow you to copy over your `bukkit.yml` and so on directly into the server directory. - -### Replacing variables inside configs - -Sometimes you have mods or plugins that require configuration information that is only available at runtime. -For example if you need to configure a plugin to connect to a database, -you don't want to include this information in your Git repository or Docker image. -Or maybe you have some runtime information like the server name that needs to be set -in your config files after the container starts. - -For those cases there is the option to replace defined variables inside your configs -with environment variables defined at container runtime. - -If you set the enviroment variable `REPLACE_ENV_VARIABLES` to `TRUE` the startup script -will go thru all files inside your `/data` volume and replace variables that match your -defined environment variables. Variables that you want to replace need to be wrapped -inside `${YOUR_VARIABLE}` curly brackets and prefixed with a dollar sign. This is the regular -syntax for enviromment variables inside strings or config files. - -Optionally you can also define a prefix to only match predefined environment variables. - -`ENV_VARIABLE_PREFIX="CFG_"` <-- this is the default prefix - -If you want use file for value (like when use secrets) you can add suffix `_FILE` to your variable name (in run command). - -There are some limitations to what characters you can use. - -| Type | Allowed Characters | -| ----- | ------------------- | -| Name | `0-9a-zA-Z_-` | -| Value | `0-9a-zA-Z_-:/=?.+` | - -Variables will be replaced in files with the following extensions: -`.yml`, `.yaml`, `.txt`, `.cfg`, `.conf`, `.properties`. - -Specific files can be excluded by listing their name (without path) in the variable `REPLACE_ENV_VARIABLES_EXCLUDES`. - -Paths can be excluded by listing them in the variable `REPLACE_ENV_VARIABLES_EXCLUDE_PATHS`. Path -excludes are recursive. Here is an example: -``` -REPLACE_ENV_VARIABLES_EXCLUDE_PATHS="/data/plugins/Essentials/userdata /data/plugins/MyPlugin" -``` - -Here is a full example where we want to replace values inside a `database.yml`. - -```yml - ---- -database: - host: ${CFG_DB_HOST} - name: ${CFG_DB_NAME} - password: ${CFG_DB_PASSWORD} -``` - -This is how your `docker-compose.yml` file could look like: - -```yml -version: "3" -# Other docker-compose examples in /examples - -services: - minecraft: - image: itzg/minecraft-server - ports: - - "25565:25565" - volumes: - - "mc:/data" - environment: - EULA: "TRUE" - ENABLE_RCON: "true" - RCON_PASSWORD: "testing" - RCON_PORT: 28016 - # enable env variable replacement - REPLACE_ENV_VARIABLES: "TRUE" - # define an optional prefix for your env variables you want to replace - ENV_VARIABLE_PREFIX: "CFG_" - # and here are the actual variables - CFG_DB_HOST: "http://localhost:3306" - CFG_DB_NAME: "minecraft" - CFG_DB_PASSWORD_FILE: "/run/secrets/db_password" - restart: always - rcon: - image: itzg/rcon - ports: - - "4326:4326" - - "4327:4327" - volumes: - - "rcon:/opt/rcon-web-admin/db" - -volumes: - mc: - rcon: - -secrets: - db_password: - file: ./db_password -``` - -The content of `db_password`: - - ug23u3bg39o-ogADSs +> NOTE: If a file was updated in the destination path and is newer than the source file from `/config`, then it will not be overwritten. ## Running a Bukkit/Spigot server @@ -460,7 +287,7 @@ If you are hosting your own copy of Bukkit/Spigot you can override the download You can build spigot from source by adding `-e BUILD_FROM_SOURCE=true` -If you have attached a host directory to the `/data` volume, then you can install plugins within the `plugins` subdirectory. You can also [attach a `/plugins` volume](#deploying-plugins-from-attached-volume). If you add plugins while the container is running, you'll need to restart it to pick those up. +Plugins can either be managed within the `plugins` subdirectory of the [data directory](#data-directory) or you can also [attach a `/plugins` volume](#deploying-plugins-from-attached-volume). If you add plugins while the container is running, you'll need to restart it to pick those up. [You can also auto-download plugins using `SPIGET_RESOURCES`.](#auto-downloading-spigotmcbukkitpapermc-plugins) @@ -705,7 +532,7 @@ in either persistent volumes or a downloadable archive. ## Deploying plugins from attached volume -There is one additional volume that can be mounted; `/plugins`. Any files in this filesystem will be copied over to the main `/data/plugins` filesystem before starting Minecraft. Set `PLUGINS_SYNC_UPDATE=false` if you want files from `/plugins` to take precedence over newer files in `/data/plugins`. +If the `/plugins` directory exists in the container, such as from an attached volume, any files in this directory will be copied over to `/data/plugins` before starting Minecraft. Set `PLUGINS_SYNC_UPDATE=false` if you want files from `/plugins` to take precedence over newer files in `/data/plugins`. This works well if you want to have a common set of plugins in a separate location, but still have multiple worlds with different server requirements in either persistent volumes or a downloadable archive. @@ -713,6 +540,8 @@ This works well if you want to have a common set of plugins in a separate locati The `SPIGET_RESOURCES` variable can be set with a comma-separated list of SpigotMC resource IDs to automatically download [SpigotMC resources/plugins](https://www.spigotmc.org/resources/) using [the spiget API](https://spiget.org/). Resources that are zip files will be expanded into the plugins directory and resources that are simply jar files will be moved there. +> NOTE: the variable is purposely spelled SPIG**E**T with an "E" + The **resource ID** can be located from the numerical part of the URL after the shortname and a dot. For example, the ID is **9089** from https://www.spigotmc.org/resources/essentialsx.9089/ @@ -722,6 +551,106 @@ For example, the following will auto-download the [EssentialsX](https://www.spig -e SPIGET_RESOURCES=9089,34315 +## Replacing variables inside configs + +Sometimes you have mods or plugins that require configuration information that is only available at runtime. +For example if you need to configure a plugin to connect to a database, +you don't want to include this information in your Git repository or Docker image. +Or maybe you have some runtime information like the server name that needs to be set +in your config files after the container starts. + +For those cases there is the option to replace defined variables inside your configs +with environment variables defined at container runtime. + +If you set the enviroment variable `REPLACE_ENV_VARIABLES` to `TRUE` the startup script +will go thru all files inside your `/data` volume and replace variables that match your +defined environment variables. Variables that you want to replace need to be wrapped +inside `${YOUR_VARIABLE}` curly brackets and prefixed with a dollar sign. This is the regular +syntax for enviromment variables inside strings or config files. + +Optionally you can also define a prefix to only match predefined environment variables. + +`ENV_VARIABLE_PREFIX="CFG_"` <-- this is the default prefix + +If you want use file for value (like when use secrets) you can add suffix `_FILE` to your variable name (in run command). + +There are some limitations to what characters you can use. + +| Type | Allowed Characters | +| ----- | ------------------- | +| Name | `0-9a-zA-Z_-` | +| Value | `0-9a-zA-Z_-:/=?.+` | + +Variables will be replaced in files with the following extensions: +`.yml`, `.yaml`, `.txt`, `.cfg`, `.conf`, `.properties`. + +Specific files can be excluded by listing their name (without path) in the variable `REPLACE_ENV_VARIABLES_EXCLUDES`. + +Paths can be excluded by listing them in the variable `REPLACE_ENV_VARIABLES_EXCLUDE_PATHS`. Path +excludes are recursive. Here is an example: +``` +REPLACE_ENV_VARIABLES_EXCLUDE_PATHS="/data/plugins/Essentials/userdata /data/plugins/MyPlugin" +``` + +Here is a full example where we want to replace values inside a `database.yml`. + +```yml + +--- +database: + host: ${CFG_DB_HOST} + name: ${CFG_DB_NAME} + password: ${CFG_DB_PASSWORD} +``` + +This is how your `docker-compose.yml` file could look like: + +```yml +version: "3" +# Other docker-compose examples in /examples + +services: + minecraft: + image: itzg/minecraft-server + ports: + - "25565:25565" + volumes: + - "mc:/data" + environment: + EULA: "TRUE" + ENABLE_RCON: "true" + RCON_PASSWORD: "testing" + RCON_PORT: 28016 + # enable env variable replacement + REPLACE_ENV_VARIABLES: "TRUE" + # define an optional prefix for your env variables you want to replace + ENV_VARIABLE_PREFIX: "CFG_" + # and here are the actual variables + CFG_DB_HOST: "http://localhost:3306" + CFG_DB_NAME: "minecraft" + CFG_DB_PASSWORD_FILE: "/run/secrets/db_password" + restart: always + rcon: + image: itzg/rcon + ports: + - "4326:4326" + - "4327:4327" + volumes: + - "rcon:/opt/rcon-web-admin/db" + +volumes: + mc: + rcon: + +secrets: + db_password: + file: ./db_password +``` + +The content of `db_password`: + + ug23u3bg39o-ogADSs + ## Running with a custom server JAR If you would like to run a custom server JAR, set `-e TYPE=CUSTOM` and pass the custom server @@ -1215,6 +1144,46 @@ disable that by passing `-e GUI=FALSE`. When the container is signalled to stop, the Minecraft process wrapper will attempt to send a "stop" command via RCON or console and waits for the process to gracefully finish. By defaul it waits 60 seconds, but that duration can be configured by setting the environment variable `STOP_DURATION` to the number of seconds. +## Autopause + +### Description + +There are various bug reports on [Mojang](https://bugs.mojang.com) about high CPU usage of servers with newer versions, even with few or no clients connected (e.g. [this one](https://bugs.mojang.com/browse/MC-149018), in fact the functionality is based on [this comment in the thread](https://bugs.mojang.com/browse/MC-149018?focusedCommentId=593606&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-593606)). + +An autopause functionality has been added to this image to monitor whether clients are connected to the server. If for a specified time no client is connected, the Java process is stopped. When knocking on the server port (e.g. by the ingame Multiplayer server overview), the process is resumed. The experience for the client does not change. + +Of course, even loaded chunks are not ticked when the process is stopped. + +**You must greatly increase or disable max-tick-time watchdog functionality.** From the server's point of view, the pausing causes a single tick to take as long as the process is stopped, so the server watchdog might intervene after the process is continued, possibly forcing a container restart. To prevent this, ensure that the `max-tick-time` in the `server.properties` file is set to a very large value or -1 to disable it entirely, which is highly recommended. That can be set with `MAX_TICK_TIME` as described in [the section below](#max-tick-time). + +> **NOTE:** Non-vanilla versions might have their own configuration file, you might have to disable their watchdogs separately (e.g. PAPER Servers). + +On startup the `server.properties` file is checked and, if applicable, a warning is printed to the terminal. When the server is created (no data available in the persistent directory), the properties file is created with the Watchdog disabled. + +The utility used to wake the server (`knock(d)`) works at network interface level. So the correct interface has to be set using the `AUTOPAUSE_KNOCK_INTERFACE` variable when using non-default networking environments (e.g. host-networking, Portainer oder NAS solutions). See the description of the variable below. + +A starting, example compose file has been provided in [examples/docker-compose-autopause.yml](examples/docker-compose-autopause.yml). + +### Enabling Autopause + +Enable the Autopause functionality by setting: + +``` +-e ENABLE_AUTOPAUSE=TRUE +``` + +The following environment variables define the behaviour of auto-pausing: +* `AUTOPAUSE_TIMEOUT_EST`, default `3600` (seconds) + describes the time between the last client disconnect and the pausing of the process (read as timeout established) +* `AUTOPAUSE_TIMEOUT_INIT`, default `600` (seconds) + describes the time between server start and the pausing of the process, when no client connects inbetween (read as timeout initialized) +* `AUTOPAUSE_TIMEOUT_KN`, default `120` (seconds) + describes the time between knocking of the port (e.g. by the main menu ping) and the pausing of the process, when no client connects inbetween (read as timeout knocked) +* `AUTOPAUSE_PERIOD`, default `10` (seconds) + describes period of the daemonized state machine, that handles the pausing of the process (resuming is done independently) +* `AUTOPAUSE_KNOCK_INTERFACE`, default `eth0` +
Describes the interface passed to the `knockd` daemon. If the default interface does not work, run the `ifconfig` command inside the container and derive the interface receiving the incoming connection from its output. The passed interface must exist inside the container. Using the loopback interface (`lo`) does likely not yield the desired results. + ## Running on RaspberryPi To run this image on a RaspberryPi 3 B+, 4, or newer, use any of the image tags [list in the Java version section](#running-minecraft-server-on-different-java-version) that specify `armv7` for the architecture, such as diff --git a/docs/level-vs-world.drawio.png b/docs/level-vs-world.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..8f4337e3d63646357c1b93c97e7dd385cad450e8 GIT binary patch literal 34180 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 U-i)$4VSyhdxSD*4?9(^@3(7-PW&i*H literal 0 HcmV?d00001 From 87f6fe6b20320690302c5e073012c466e412cefc Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Fri, 26 Mar 2021 19:11:38 -0500 Subject: [PATCH 22/27] Fixed $LEVEL path in directory structure diagram --- docs/level-vs-world.drawio.png | Bin 34180 -> 32884 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/level-vs-world.drawio.png b/docs/level-vs-world.drawio.png index 8f4337e3d63646357c1b93c97e7dd385cad450e8..2a600cfe3bd780009529b0300d8f8f3a3699fedb 100644 GIT binary patch literal 32884 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 U-i)$4VSyhdxSD*4?9(^@3(7-PW&i*H From 02ba96c42110855a9ae9636183d02776af5a1baf Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Sat, 27 Mar 2021 18:38:43 -0500 Subject: [PATCH 23/27] docs: Added -it to initial examples --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9a3ebecf..21850dcd 100644 --- a/README.md +++ b/README.md @@ -11,21 +11,21 @@ latest snapshot. See the _Versions_ section below for more information. To simply use the latest stable version, run - docker run -d -p 25565:25565 --name mc -e EULA=TRUE itzg/minecraft-server + docker run -d -it -p 25565:25565 -e EULA=TRUE itzg/minecraft-server where the standard server port, 25565, will be exposed on your host machine. If you want to serve up multiple Minecraft servers or just use an alternate port, change the host-side port mapping such as - docker run -p 25566:25565 ... + ... -p 25566:25565 ... will serve your Minecraft server on your host's port 25566 since the `-p` syntax is `host-port`:`container-port`. -Speaking of multiple servers, it's handy to give your containers explicit names using `--name`, such as +Speaking of multiple servers, it's handy to give your containers explicit names using `--name`, such as naming this one "mc" - docker run -d -p 25565:25565 --name mc itzg/minecraft-server + ... --name mc itzg/minecraft-server With that you can easily view the logs, stop, or re-start the container: @@ -35,7 +35,8 @@ With that you can easily view the logs, stop, or re-start the container: docker stop mc docker start mc -*Be sure to always include `-e EULA=TRUE` in your commands, as Mojang/Microsoft requires EULA acceptance.* + +> Be sure to always include `-e EULA=TRUE` in your commands, as Mojang/Microsoft requires EULA acceptance. ## Looking for a Bedrock Dedicated Server From 4628da7ea27a3f73860728f033e247a9224fc48b Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Sat, 27 Mar 2021 18:39:22 -0500 Subject: [PATCH 24/27] docs: Fixed alternate exposed port example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 21850dcd..bb1221a4 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ where the standard server port, 25565, will be exposed on your host machine. If you want to serve up multiple Minecraft servers or just use an alternate port, change the host-side port mapping such as - ... -p 25566:25565 ... + ... -p 25566:25565 ... will serve your Minecraft server on your host's port 25566 since the `-p` syntax is `host-port`:`container-port`. From f6c71e27d806165586b79bec06c12e41647a3c31 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Sat, 27 Mar 2021 18:47:42 -0500 Subject: [PATCH 25/27] docs: described converting anonymous data volume --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index bb1221a4..2a5de4e8 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,27 @@ services: - ./minecraft-data:/data ``` +### Converting anonymous `/data` volume to named volume + +If you had used the commands in the first section, without the `-v` volume attachment, then an anonymous data volume was created by Docker. You can later bring over that content to a named or host attached volume using the following procedure. + +> In this example, it is assumed the original container was given a `--name` of "mc", so change the container identifier accordingly. + +First, stop the existing container: +```shell +docker stop mc +``` + +Use a temporary container to copy over the anonymous volume's content into a named volume, "mc" in this case: +```shell +docker run --rm --volumes-from mc -v mc:/new alpine cp -avT /data /new +``` + +Now you can recreate the container with any environment variable changes, etc by attaching the named volume created from the previous step: +```shell +docker run -d -it --name mc-new -v mc:/data -p 25565:25565 -e EULA=TRUE -e MEMORY=2G itzg/minecraft-server +``` + ## Versions To use a different Minecraft version, pass the `VERSION` environment variable, which can have the value From 327538a98f7dd8d5b0c34c20d0e5dfba985cb38c Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Sat, 27 Mar 2021 18:49:58 -0500 Subject: [PATCH 26/27] docs: shifted timezone info later --- README.md | 46 ++++++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 2a5de4e8..438e8533 100644 --- a/README.md +++ b/README.md @@ -82,34 +82,6 @@ and attach from another machine: Unless you're on a home/private LAN, you should [enable TLS access](https://docs.docker.com/articles/https/). -## EULA Support - -Mojang now requires accepting the [Minecraft EULA](https://account.mojang.com/documents/minecraft_eula). To accept add - - -e EULA=TRUE - -such as - - docker run -d -it -e EULA=TRUE -p 25565:25565 --name mc itzg/minecraft-server - -## Timezone Configuration - -You can configure the timezone to match yours by setting the `TZ` environment variable: - - -e TZ=Europe/London - -such as: - - docker run -d -it -e TZ=Europe/London -p 25565:25565 --name mc itzg/minecraft-server - -Or mounting `/etc/timezone` as readonly (not supported on Windows): - - -v /etc/timezone:/etc/timezone:ro - -such as: - - docker run -d -it -v /etc/timezone:/etc/timezone:ro -p 25565:25565 --name mc itzg/minecraft-server - ## Data Directory Everything the container manages is located under the **container's** `/data` path, as shown here: @@ -1125,6 +1097,24 @@ via a `JVM_XX_OPTS` environment variable. For some cases, if e.g. after removing mods, it could be necessary to startup minecraft with an additional `-D` parameter like `-Dfml.queryResult=confirm`. To address this you can use the environment variable `JVM_DD_OPTS`, which builds the params from a given list of values separated by space, but without the `-D` prefix. To make things running under systems (e.g. Plesk), which doesn't allow `=` inside values, a `:` (colon) could be used instead. The upper example would look like this: `JVM_DD_OPTS=fml.queryResult:confirm`, and will be converted to `-Dfml.queryResult=confirm`. +## Timezone Configuration + +You can configure the timezone to match yours by setting the `TZ` environment variable: + + -e TZ=Europe/London + +such as: + + docker run -d -it -e TZ=Europe/London -p 25565:25565 --name mc itzg/minecraft-server + +Or mounting `/etc/timezone` as readonly (not supported on Windows): + + -v /etc/timezone:/etc/timezone:ro + +such as: + + docker run -d -it -v /etc/timezone:/etc/timezone:ro -p 25565:25565 --name mc itzg/minecraft-server + ### Enable Remote JMX for Profiling To enable remote JMX, such as for profiling with VisualVM or JMC, add the environment variable `ENABLE_JMX=true`, set `JMX_HOST` to the IP/host running the Docker container, and add a port forwarding of TCP port 7091, such as: From 7aa47e2a60cd0360103480fb1535875dc6e2c1d6 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Mon, 29 Mar 2021 21:14:21 -0500 Subject: [PATCH 27/27] Remove existing world data when FORCE_WORLD_COPY (#816) --- start-finalSetupWorld | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/start-finalSetupWorld b/start-finalSetupWorld index 96537246..cfbd4ad0 100644 --- a/start-finalSetupWorld +++ b/start-finalSetupWorld @@ -14,6 +14,13 @@ else fi if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] ); then + if isTrue "${FORCE_WORLD_COPY}"; then + log "Removing existing world data in $worldDest ${worldDest}_nether ${worldDest}_the_end" + rm -rf "$worldDest" \ + "${worldDest}_nether" \ + "${worldDest}_the_end" + fi + if isURL $WORLD; then curl -fsSL "$WORLD" -o /tmp/world.zip zipSrc=/tmp/world.zip @@ -59,8 +66,8 @@ if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] ); if [ "$TYPE" = "SPIGOT" ]; then # Reorganise if a Spigot server log "Moving End and Nether maps to Spigot location" - [ -d "$worldDest/DIM1" ] && mv -f "$worldDest/DIM1" "/data/${LEVEL}_the_end" - [ -d "$worldDest/DIM-1" ] && mv -f "$worldDest/DIM-1" "/data/${LEVEL}_nether" + [ -d "$worldDest/DIM1" ] && mv -f "$worldDest/DIM1" "${worldDest}_the_end" + [ -d "$worldDest/DIM-1" ] && mv -f "$worldDest/DIM-1" "${worldDest}_nether" fi fi