[mc] Robust handling of Forge, Bukkit, and Spigot version selection

* refactor server.properties sed ops into a utility function
* also switch to jq instead of jsawk
* simplify to BUILD_FROM_SOURCE from BUILD_SPIGOT_FROM_SOURCE
Fixes #70
This commit is contained in:
Geoff Bourne
2016-04-23 22:23:55 -05:00
parent 0ea4ea7d0c
commit cf5d194b14
4 changed files with 100 additions and 192 deletions
+2 -5
View File
@@ -2,21 +2,18 @@ FROM java:8
MAINTAINER itzg MAINTAINER itzg
ENV APT_GET_UPDATE 2015-10-03 ENV APT_GET_UPDATE 2016-04-23
RUN apt-get update RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y \ RUN DEBIAN_FRONTEND=noninteractive apt-get install -y \
libmozjs-24-bin \
imagemagick \ imagemagick \
lsof \ lsof \
nano \ nano \
sudo \ sudo \
vim \ vim \
jq \
&& apt-get clean && apt-get clean
RUN update-alternatives --install /usr/bin/js js /usr/bin/js24 100
RUN wget -O /usr/bin/jsawk https://github.com/micha/jsawk/raw/master/jsawk
RUN chmod +x /usr/bin/jsawk
RUN useradd -M -s /bin/false --uid 1000 minecraft \ RUN useradd -M -s /bin/false --uid 1000 minecraft \
&& mkdir /data \ && mkdir /data \
&& mkdir /config \ && mkdir /config \
+12 -12
View File
@@ -147,7 +147,7 @@ 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 Any files in either of these filesystems will be copied over to the main
`/data` filesystem before starting Minecraft. `/data` filesystem before starting Minecraft.
This works well if you want to have a common set of modules in a separate 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 location, but still have multiple worlds with different server requirements
in either persistent volumes or a downloadable archive. in either persistent volumes or a downloadable archive.
@@ -164,7 +164,7 @@ available. The latest build in this branch will be used.
You can install Bukkit plugins in two ways. You can install Bukkit plugins in two ways.
You can build spigot from source by adding `-e BUILD_SPIGOT_FROM_SOURCE=true` You can build spigot from source by adding `-e BUILD_FROM_SOURCE=true`
### Using the /data volume ### Using the /data volume
@@ -200,7 +200,7 @@ There is one additional volume that can be mounted; `/plugins`.
Any files in this filesystem will be copied over to the main Any files in this filesystem will be copied over to the main
`/data/plugins` filesystem before starting Minecraft. `/data/plugins` filesystem before starting Minecraft.
This works well if you want to have a common set of plugins in a separate 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 location, but still have multiple worlds with different server requirements
in either persistent volumes or a downloadable archive. in either persistent volumes or a downloadable archive.
@@ -274,7 +274,7 @@ To use rcon use the `ENABLE_RCON` and `RCON_PASSORD` variables.
By default rcon port will be `25575` but can easily be changed with the `RCON_PORT` variable. By default rcon port will be `25575` but can easily be changed with the `RCON_PORT` variable.
docker run -d -e ENABLE_RCON=true -e RCON_PASSWORD=testing docker run -d -e ENABLE_RCON=true -e RCON_PASSWORD=testing
### Query ### Query
Enabling this will enable the gamespy query protocol. Enabling this will enable the gamespy query protocol.
@@ -286,13 +286,13 @@ By default the query port will be `25565` (UDP) but can easily be changed with t
### Max players ### Max players
By default max players is 20, you can increase this with the `MAX_PLAYERS` variable. By default max players is 20, you can increase this with the `MAX_PLAYERS` variable.
docker run -d -e MAX_PLAYERS=50 docker run -d -e MAX_PLAYERS=50
### Max world size ### Max world size
This sets the maximum possible size in blocks, expressed as a radius, that the world border can obtain. This sets the maximum possible size in blocks, expressed as a radius, that the world border can obtain.
docker run -d -e MAX_WORLD_SIZE=10000 docker run -d -e MAX_WORLD_SIZE=10000
@@ -338,7 +338,7 @@ If set to true, players will be set to spectator mode if they die.
### Max Build Height ### Max Build Height
The maximum height in which building is allowed. The maximum height in which building is allowed.
Terrain may still naturally generate above a low height limit. Terrain may still naturally generate above a low height limit.
docker run -d -e MAX_BUILD_HEIGHT=256 docker run -d -e MAX_BUILD_HEIGHT=256
@@ -370,7 +370,7 @@ Determines if villagers will be spawned.
### View Distance ### View Distance
Sets the amount of world data the server sends the client, measured in chunks in each direction of the player (radius, not diameter). Sets the amount of world data the server sends the client, measured in chunks in each direction of the player (radius, not diameter).
It determines the server-side viewing distance. It determines the server-side viewing distance.
docker run -d -e VIEW_DISTANCE=10 docker run -d -e VIEW_DISTANCE=10
@@ -448,7 +448,7 @@ where the default is "world":
Instead of mounting the `/data` volume, you can instead specify the URL of Instead of mounting the `/data` volume, you can instead specify the URL of
a ZIP file containing an archived world. This will be downloaded, and a ZIP file containing an archived world. This will be downloaded, and
unpacked in the `/data` directory; if it does not contain a subdirectory unpacked in the `/data` directory; if it does not contain a subdirectory
called `world/` then it will be searched for a file `level.dat` and the called `world/` then it will be searched for a file `level.dat` and the
containing subdirectory renamed to `world`. This means that most of the containing subdirectory renamed to `world`. This means that most of the
archived Minecraft worlds downloadable from the Internet will already be in archived Minecraft worlds downloadable from the Internet will already be in
the correct format. the correct format.
@@ -468,7 +468,7 @@ name of a linked container.
### Downloadable mod/plugin pack for Forge, Bukkit, and Spigot Servers ### Downloadable mod/plugin pack for Forge, Bukkit, and Spigot Servers
Like the `WORLD` option above, you can specify the URL of a "mod pack" Like the `WORLD` option above, you can specify the URL of a "mod pack"
to download and install into `mods` for Forge or `plugins` for Bukkit/Spigot. to download and install into `mods` for Forge or `plugins` for Bukkit/Spigot.
To use this option pass the environment variable `MODPACK`, such as To use this option pass the environment variable `MODPACK`, such as
docker run -d -e MODPACK=http://www.example.com/mods/modpack.zip ... docker run -d -e MODPACK=http://www.example.com/mods/modpack.zip ...
+80 -174
View File
@@ -21,16 +21,16 @@ fi
echo "Checking version information." echo "Checking version information."
case "X$VERSION" in case "X$VERSION" in
X|XLATEST|Xlatest) X|XLATEST|Xlatest)
VANILLA_VERSION=`wget -O - https://s3.amazonaws.com/Minecraft.Download/versions/versions.json | jsawk -n 'out(this.latest.release)'` VANILLA_VERSION=`curl -sSL https://s3.amazonaws.com/Minecraft.Download/versions/versions.json | jq -r '.latest.release'`
;; ;;
XSNAPSHOT|Xsnapshot) XSNAPSHOT|Xsnapshot)
VANILLA_VERSION=`wget -O - https://s3.amazonaws.com/Minecraft.Download/versions/versions.json | jsawk -n 'out(this.latest.snapshot)'` VANILLA_VERSION=`curl -sSL https://s3.amazonaws.com/Minecraft.Download/versions/versions.json | jq -r '.latest.snapshot'`
;; ;;
X[1-9]*) X[1-9]*)
VANILLA_VERSION=$VERSION VANILLA_VERSION=$VERSION
;; ;;
*) *)
VANILLA_VERSION=`wget -O - https://s3.amazonaws.com/Minecraft.Download/versions/versions.json | jsawk -n 'out(this.latest.release)'` VANILLA_VERSION=`curl -sSL https://s3.amazonaws.com/Minecraft.Download/versions/versions.json | jq -r '.latest.release'`
;; ;;
esac esac
@@ -39,53 +39,18 @@ cd /data
echo "Checking type information." echo "Checking type information."
case "$TYPE" in case "$TYPE" in
*BUKKIT|*bukkit|SPIGOT|spigot) *BUKKIT|*bukkit|SPIGOT|spigot)
TYPE=SPIGOT if [[ "$BUILD_SPIGOT_FROM_SOURCE" = TRUE || "$BUILD_SPIGOT_FROM_SOURCE" = true || "$BUILD_FROM_SOURCE" = TRUE || "$BUILD_FROM_SOURCE" = true ]]; then
if [ -z "$BUILD_SPIGOT_FROM_SOURCE" ]; then
case "$TYPE" in
*BUKKIT|*bukkit)
echo "Downloading latest CraftBukkit $VANILLA_VERSION server ..."
SERVER=craftbukkit_server.jar
;;
*)
echo "Downloading latest Spigot $VANILLA_VERSION server ..."
SERVER=spigot_server.jar
;;
esac
case $VANILLA_VERSION in
1.8*)
URL=/spigot18/$SERVER
;;
1.9*)
URL=/spigot19/$SERVER
;;
*)
echo "That version of $SERVER is not available."
exit 1
;;
esac
#attempt https, and if it fails, fallback to http and download that way. Display error if neither works.
wget -q -N $SERVER https://getspigot.org$URL || \
(echo "Falling back to http, unable to contact server using https..." && \
wget -q -N $SERVER http://getspigot.org$URL) || \
echo "Unable to download new copy of spigot server"
fi
if [ "$BUILD_SPIGOT_FROM_SOURCE" = true ]; then
echo "Building spigot from source, might take a while, get some coffee"
if [ ! -f /data/spigot_server.jar ]; then if [ ! -f /data/spigot_server.jar ]; then
echo "Downloading and building buildtools for version $VANILLA_VERSION" echo "Building Spigot $VANILLA_VERSION from source, might take a while, get some coffee"
mkdir /data/temp mkdir /data/temp
cd /data/temp cd /data/temp
wget -P /data/temp https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar && \ wget -q -P /data/temp https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar && \
java -jar /data/temp/BuildTools.jar --rev $VANILLA_VERSION && \ java -jar /data/temp/BuildTools.jar --rev $VANILLA_VERSION 2>&1 |tee /data/spigot_build.log| while read l; do echo -n .; done; echo "done"
find * -maxdepth 0 ! -name '*.jar' -exec rm -rf {} \; && \ mv spigot-*.jar /data/spigot_server.jar
chown minecraft:minecraft spigot-*.jar && \
chown minecraft:minecraft craftbukkit-*.jar && \
mv spigot-*.jar /data/spigot_server.jar && \
mv craftbukkit-*.jar /data/craftbukkit_server.jar mv craftbukkit-*.jar /data/craftbukkit_server.jar
echo "Cleaning up" echo "Cleaning up"
rm -rf /data/temp rm -rf /data/temp
cd /data cd /data
fi fi
case "$TYPE" in case "$TYPE" in
*BUKKIT|*bukkit) *BUKKIT|*bukkit)
@@ -95,7 +60,29 @@ case "$TYPE" in
SERVER=spigot_server.jar SERVER=spigot_server.jar
;; ;;
esac esac
fi else
case "$TYPE" in
*BUKKIT|*bukkit)
match="Craftbukkit $VANILLA_VERSION"
SERVER=craftbukkit.jar
;;
*)
match="Spigot $VANILLA_VERSION"
SERVER=spigot.jar
;;
esac
curl -o /tmp/versions -sSL https://getspigot.org/api/getversions
downloadUrl=$(cat /tmp/versions | jq -r ".[] | select(.version == \"$match\") | .downloadUrl")
if [[ -n $downloadUrl ]]; then
echo "Downloading $match"
curl -o $SERVER -sSL "$downloadUrl"
else
echo "ERROR: Version $VANILLA_VERSION is not supported for $TYPE"
echo " Refer to http://getspigot.org for supported versions"
exit 2
fi
fi
;; ;;
FORGE|forge) FORGE|forge)
@@ -104,12 +91,21 @@ case "$TYPE" in
echo "Checking Forge version information." echo "Checking Forge version information."
case $FORGEVERSION in case $FORGEVERSION in
RECOMMENDED) RECOMMENDED)
FORGE_VERSION=`wget -O - http://files.minecraftforge.net/maven/net/minecraftforge/forge/promotions_slim.json | jsawk -n "out(this.promos['$norm-recommended'])"` curl -o /tmp/forge.json -sSL http://files.minecraftforge.net/maven/net/minecraftforge/forge/promotions_slim.json
FORGE_VERSION=$(cat /tmp/forge.json | jq -r ".promos[\"$norm-recommended\"]")
if [ $FORGE_VERSION = null ]; then
FORGE_VERSION=$(cat /tmp/forge.json | jq -r ".promos[\"$norm-latest\"]")
if [ $FORGE_VERSION = null ]; then
echo "ERROR: Version $FORGE_VERSION is not supported by Forge"
echo " Refer to http://files.minecraftforge.net/ for supported versions"
exit 2
fi
fi
;; ;;
*) *)
FORGE_VERSION=$FORGEVERSION FORGE_VERSION=$FORGEVERSION
;; ;;
esac esac
@@ -151,10 +147,6 @@ case "$TYPE" in
esac esac
#Switch to minecraft user
echo "...switching to user 'minecraft'"
su - minecraft
# If supplied with a URL for a world, download it and unpack # If supplied with a URL for a world, download it and unpack
if [[ "$WORLD" ]]; then if [[ "$WORLD" ]]; then
case "X$WORLD" in case "X$WORLD" in
@@ -210,6 +202,16 @@ case "X$MODPACK" in
esac esac
fi fi
function setServerProp {
local prop=$1
local var=$2
if [ -n "$var" ]; then
echo "Setting $prop to $var"
sed -i "/$prop\s*=/ c $prop=$var" /data/server.properties
fi
}
if [ ! -e server.properties ]; then if [ ! -e server.properties ]; then
echo "Creating server.properties" echo "Creating server.properties"
cp /tmp/server.properties . cp /tmp/server.properties .
@@ -220,122 +222,31 @@ if [ ! -e server.properties ]; then
sed -i "/white-list\s*=/ c white-list=true" /data/server.properties sed -i "/white-list\s*=/ c white-list=true" /data/server.properties
fi fi
if [ -n "$MOTD" ]; then setServerProp "motd" "$MOTD"
echo "Setting motd" setServerProp "allow-nether" "$ALLOW_NETHER"
sed -i "/motd\s*=/ c motd=$MOTD" /data/server.properties setServerProp "announce-player-achievements" "$ANNOUNCE_PLAYER_ACHIEVEMENTS"
fi setServerProp "enable-command-block" "$ENABLE_COMMAND_BLOCK"
setServerProp "spawn-animals" "$SPAWN_ANIMAILS"
if [ -n "$ALLOW_NETHER" ]; then setServerProp "spawn-monsters" "$SPAWN_MONSTERS"
echo "Setting allow-nether" setServerProp "spawn-npcs" "$SPAWN_NPCS"
sed -i "/allow-nether\s*=/ c allow-nether=$ALLOW_NETHER" /data/server.properties setServerProp "generate-structures" "$GENERATE_STRUCTURES"
fi setServerProp "spawn-npcs" "$SPAWN_NPCS"
setServerProp "view-distance" "$VIEW_DISTANCE"
if [ -n "$ANNOUNCE_PLAYER_ACHIEVEMENTS" ]; then setServerProp "hardcore" "$HARDCORE"
echo "Setting announce-player-achievements" setServerProp "max-build-height" "$MAX_BUILD_HEIGHT"
sed -i "/announce-player-achievements\s*=/ c announce-player-achievements=$ANNOUNCE_PLAYER_ACHIEVEMENTS" /data/server.properties setServerProp "force-gamemode" "$FORCE_GAMEMODE"
fi setServerProp "hardmax-tick-timecore" "$MAX_TICK_TIME"
setServerProp "enable-query" "$ENABLE_QUERY"
if [ -n "$ENABLE_COMMAND_BLOCK" ]; then setServerProp "query.port" "$QUERY_PORT"
echo "Setting enable-command-block" setServerProp "enable-rcon" "$ENABLE_RCON"
sed -i "/enable-command-block\s*=/ c enable-command-block=$ENABLE_COMMAND_BLOCK" /data/server.properties setServerProp "rcon.password" "$RCON_PASSWORD"
fi setServerProp "rcon.port" "$RCON_PORT"
setServerProp "max-players" "$MAX_PLAYERS"
if [ -n "$SPAWN_ANIMAILS" ]; then setServerProp "max-world-size" "$MAX_WORLD_SIZE"
echo "Setting spawn-animals" setServerProp "level-name" "$LEVEL"
sed -i "/spawn-animals\s*=/ c spawn-animals=$SPAWN_ANIMAILS" /data/server.properties setServerProp "level-seed" "$SEED"
fi setServerProp "pvp" "$PVP"
setServerProp "generator-settings" "$GENERATOR_SETTINGS"
if [ -n "$SPAWN_MONSTERS" ]; then
echo "Setting spawn-monsters"
sed -i "/spawn-monsters\s*=/ c spawn-monsters=$SPAWN_MONSTERS" /data/server.properties
fi
if [ -n "$SPAWN_NPCS" ]; then
echo "Setting spawn-npcs"
sed -i "/spawn-npcs\s*=/ c spawn-npcs=$SPAWN_NPCS" /data/server.properties
fi
if [ -n "$GENERATE_STRUCTURES" ]; then
echo "Setting generate-structures"
sed -i "/generate-structures\s*=/ c generate-structures=$GENERATE_STRUCTURES" /data/server.properties
fi
if [ -n "$VIEW_DISTANCE" ]; then
echo "Setting view-distance"
sed -i "/view-distance\s*=/ c view-distance=$VIEW_DISTANCE" /data/server.properties
fi
if [ -n "$HARDCORE" ]; then
echo "Setting hardcore"
sed -i "/hardcore\s*=/ c hardcore=$HARDCORE" /data/server.properties
fi
if [ -n "$MAX_BUILD_HEIGHT" ]; then
echo "Setting max-build-height"
sed -i "/max-build-height\s*=/ c max-build-height=$MAX_BUILD_HEIGHT" /data/server.properties
fi
if [ -n "$FORCE_GAMEMODE" ]; then
echo "Setting force-gamemode"
sed -i "/force-gamemode\s*=/ c force-gamemode=$FORCE_GAMEMODE" /data/server.properties
fi
if [ -n "$MAX_TICK_TIME" ]; then
echo "Setting max-tick-time"
sed -i "/max-tick-time\s*=/ c max-tick-time=$MAX_TICK_TIME" /data/server.properties
fi
if [ -n "$ENABLE_QUERY" ]; then
echo "Enabling query"
sed -i "/enable-query\s*=/ c enable-query=$ENABLE_QUERY" /data/server.properties
fi
if [ -n "$QUERY_PORT" ]; then
echo "Setting query port"
sed -i "/query.port\s*=/ c query.port=$QUERY_PORT" /data/server.properties
fi
if [ -n "$ENABLE_RCON" ]; then
echo "Enabling rcon"
sed -i "/enable-rcon\s*=/ c enable-rcon=$ENABLE_RCON" /data/server.properties
fi
if [ -n "$RCON_PASSWORD" ]; then
echo "Setting rcon password to $RCON_PASSWORD"
sed -i "/rcon.password\s*=/ c rcon.password=$RCON_PASSWORD" /data/server.properties
fi
if [ -n "$RCON_PORT" ]; then
echo "Setting rcon port"
sed -i "/rcon.port\s*=/ c rcon.port=$RCON_PORT" /data/server.properties
fi
if [ -n "$MAX_PLAYERS" ]; then
echo "Setting max players"
sed -i "/max-players\s*=/ c max-players=$MAX_PLAYERS" /data/server.properties
fi
if [ -n "$MAX_WORLD_SIZE" ]; then
echo "Setting max world size"
sed -i "/max-world-size\s*=/ c max-world-size=$MAX_WORLD_SIZE" /data/server.properties
fi
if [ -n "$LEVEL" ]; then
echo "Setting level name"
sed -i "/level-name\s*=/ c level-name=$LEVEL" /data/server.properties
fi
if [ -n "$SEED" ]; then
echo "Setting seed"
sed -i "/level-seed\s*=/ c level-seed=$SEED" /data/server.properties
fi
if [ -n "$PVP" ]; then
echo "Setting PVP"
sed -i "/pvp\s*=/ c pvp=$PVP" /data/server.properties
fi
if [ -n "$LEVEL_TYPE" ]; then if [ -n "$LEVEL_TYPE" ]; then
# normalize to uppercase # normalize to uppercase
@@ -353,11 +264,6 @@ if [ ! -e server.properties ]; then
esac esac
fi fi
if [ -n "$GENERATOR_SETTINGS" ]; then
echo "Setting generator settings"
sed -i "/generator-settings\s*=/ c generator-settings=$GENERATOR_SETTINGS" /data/server.properties
fi
if [ -n "$DIFFICULTY" ]; then if [ -n "$DIFFICULTY" ]; then
echo "Setting difficulty" echo "Setting difficulty"
case $DIFFICULTY in case $DIFFICULTY in
+6 -1
View File
@@ -11,4 +11,9 @@ while lsof -- /start-minecraft; do
echo -n "." echo -n "."
sleep 1 sleep 1
done done
exec /start-minecraft
mkdir /home/minecraft
chown minecraft: /home/minecraft
echo "Switching to user 'minecraft'"
exec sudo -E -u minecraft /start-minecraft