diff --git a/minecraft-server/Dockerfile b/minecraft-server/Dockerfile index 9d8c84b5..d30a6ebb 100644 --- a/minecraft-server/Dockerfile +++ b/minecraft-server/Dockerfile @@ -14,7 +14,8 @@ RUN useradd -M -s /bin/false --uid 1000 minecraft \ && mkdir /data \ && mkdir /config \ && mkdir /mods \ - && chown minecraft:minecraft /data /config /mods + && mkdir /plugins \ + && chown minecraft:minecraft /data /config /mods /plugins EXPOSE 25565 @@ -24,6 +25,7 @@ COPY start-minecraft.sh /start-minecraft VOLUME ["/data"] VOLUME ["/mods"] VOLUME ["/config"] +VOLUME ["/plugins"] COPY server.properties /tmp/server.properties WORKDIR /data @@ -36,4 +38,4 @@ ENV UID=1000 ENV MOTD A Minecraft Server Powered by Docker ENV JVM_OPTS -Xmx1024M -Xms1024M ENV TYPE=VANILLA VERSION=LATEST FORGEVERSION=RECOMMENDED LEVEL=world PVP=true DIFFICULTY=easy \ - LEVEL_TYPE=DEFAULT GENERATOR_SETTINGS= WORLD= + LEVEL_TYPE=DEFAULT GENERATOR_SETTINGS= WORLD= MODPACK= diff --git a/minecraft-server/README.md b/minecraft-server/README.md index 88a41392..ef671b4c 100644 --- a/minecraft-server/README.md +++ b/minecraft-server/README.md @@ -146,6 +146,57 @@ 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. +## Running a Bukkit/Spigot server + +Enable Bukkit/Spigot server mode by adding a `-e TYPE=BUKKIT -e VERSION=1.8` or `-e TYPE=SPIGOT -e VERSION=1.8` to your command-line. + +The VERSION option should be set to 1.8, as this is the only version of CraftBukkit and Spigot currently +available. The latest build in this branch will be used. + + $ docker run -d -v /path/on/host:/data \ + -e TYPE=SPIGOT -e VERSION=1.8 \ + -p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server + +You can install Bukkit plugins in two ways. + +### Using the /data volume + +This is the easiest way if you are using a persistent `/data` mount. + +To do this, you will need to attach the container's `/data` directory +(see "Attaching data directory to host filesystem”). +Then, you can add plugins to the `/path/on/host/plugins` folder you chose. From the example above, +the `/path/on/host` folder contents look like: + +``` +/path/on/host +├── plugins +│   └── ... INSTALL PLUGINS HERE ... +├── ops.json +├── server.properties +├── whitelist.json +└── ... +``` + +If you add plugins 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 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. + +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. + ## Using Docker Compose Rather than type the server options below, the port mappings above, etc @@ -301,6 +352,18 @@ will be deleted when the container is deleted. you should use an IP address or a globally resolveable FQDN, or else the name of a linked container. +### Downloadable mod/plugin pack for Forge, Bukkit, and Spigot Servers + +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 use this option pass the environment variable `MODPACK`, such as + + docker run -d -e MODPACK=http://www.example.com/mods/modpack.zip ... + +**NOTE:** The referenced URL must be a zip file with one or more jar files at the +top level of the zip archive. Make sure the jars are compatible with the +particular `TYPE` of server you are running. + ## JVM Configuration ### Memory Limit diff --git a/minecraft-server/start-minecraft.sh b/minecraft-server/start-minecraft.sh index 28b12840..a98238ac 100755 --- a/minecraft-server/start-minecraft.sh +++ b/minecraft-server/start-minecraft.sh @@ -33,19 +33,35 @@ esac cd /data -echo "Checking minecraft / forge type information." +echo "Checking type information." case "$TYPE" in - VANILLA) - SERVER="minecraft_server.$VANILLA_VERSION.jar" + *BUKKIT|*bukkit|SPIGOT|spigot) + TYPE=SPIGOT + case "$TYPE" in + *BUKKIT|*bukkit) + echo "Downloading latest CraftBukkit 1.8 server ..." + SERVER=craftbukkit_server.jar + ;; + *) + echo "Downloading latest Spigot 1.8 server ..." + SERVER=spigot_server.jar + ;; + esac + case $VANILLA_VERSION in + 1.8*) + URL=/spigot18/$SERVER + ;; + *) + echo "That version of $SERVER is not available." + exit 1 + ;; + esac + wget -q https://getspigot.org$URL + ;; - if [ ! -e $SERVER ]; then - echo "Downloading $SERVER ..." - wget -q https://s3.amazonaws.com/Minecraft.Download/versions/$VANILLA_VERSION/$SERVER - fi - ;; - - FORGE) + FORGE|forge) # norm := the official Minecraft version as Forge is tracking it. dropped the third part starting with 1.8 + TYPE=FORGE case $VANILLA_VERSION in 1.7.*) norm=$VANILLA_VERSION @@ -56,16 +72,16 @@ case "$TYPE" in ;; esac - echo "Checking Forge version information." - case $FORGEVERSION in - RECOMMENDED) + echo "Checking Forge version information." + case $FORGEVERSION in + RECOMMENDED) FORGE_VERSION=`wget -O - http://files.minecraftforge.net/maven/net/minecraftforge/forge/promotions_slim.json | jsawk -n "out(this.promos['$norm-recommended'])"` - ;; + ;; - *) + *) FORGE_VERSION=$FORGEVERSION - ;; - esac + ;; + esac # URL format changed for 1.7.10 from 10.13.2.1300 sorted=$((echo $FORGE_VERSION; echo 10.13.2.1300) | sort -V | head -1) @@ -87,11 +103,27 @@ case "$TYPE" in fi ;; + VANILLA|vanilla) + SERVER="minecraft_server.$VANILLA_VERSION.jar" + + if [ ! -e $SERVER ]; then + echo "Downloading $SERVER ..." + wget -q https://s3.amazonaws.com/Minecraft.Download/versions/$VANILLA_VERSION/$SERVER + fi + ;; + + *) + echo "Invalid type: '$TYPE'" + echo "Must be: VANILLA, FORGE, SPIGOT" + exit 1 + ;; + esac # If supplied with a URL for a world, download it and unpack +if [[ "$WORLD" ]]; then case "X$WORLD" in - X[Hh][Tt][Tt][Pp]*[Zz][iI][pP]) + X[Hh][Tt][Tt][Pp]*) echo "Downloading world via HTTP" echo "$WORLD" wget -q -O - "$WORLD" > /data/world.zip @@ -108,11 +140,40 @@ case "X$WORLD" in fi done fi + if [ "$TYPE" = "SPIGOT" ]; then + # Reorganise if a Spigot server + echo "Moving End and Nether maps to Spigot location" + [ -d "/data/world/DIM1" ] && mv -f "/data/world/DIM1" "/data/world_the_end" + [ -d "/data/world/DIM-1" ] && mv -f "/data/world/DIM-1" "/data/world_nether" + fi ;; *) echo "Invalid URL given for world: Must be HTTP or HTTPS and a ZIP file" ;; esac +fi + +# If supplied with a URL for a modpack (simple zip of jars), download it and unpack +if [[ "$MODPACK" ]]; then +case "X$MODPACK" in + X[Hh][Tt][Tt][Pp]*[Zz][iI][pP]) + echo "Downloading mod/plugin pack via HTTP" + echo "$MODPACK" + wget -q -O /tmp/modpack.zip "$MODPACK" + if [ "$TYPE" = "SPIGOT" ]; then + mkdir -p /data/plugins + unzip -d /data/plugins /tmp/modpack.zip + else + mkdir -p /data/mods + unzip -d /data/mods /tmp/modpack.zip + fi + rm -f /tmp/modpack.zip + ;; + *) + echo "Invalid URL given for modpack: Must be HTTP or HTTPS and a ZIP file" + ;; +esac +fi if [ ! -e server.properties ]; then cp /tmp/server.properties . @@ -253,6 +314,13 @@ do fi done +if [ "$TYPE" = "SPIGOT" ]; then + echo Copying any Bukkit plugins over + if [ -d /plugins ]; then + cp -r /plugins /data + fi +fi + # If we have a bootstrap.txt file... feed that in to the server stdin if [ -f /data/bootstrap.txt ]; then @@ -260,3 +328,5 @@ then else exec java $JVM_OPTS -jar $SERVER fi + +exec java $JVM_OPTS -jar $SERVER