From 813b9de410fe52a0e04379258db8905caaedecbc Mon Sep 17 00:00:00 2001 From: Kris Lamoureux Date: Fri, 17 May 2024 23:58:46 -0400 Subject: [PATCH] Create specific Dockerfiles for Minecraft setups - Decompose Dockerfile into modular components - Establish building JRE and JDK images from Docker.java - Establish Dockerfile.vanilla for vanilla server setup - Establish Dockerfile.bukkit for Spigot and CraftBukkit - Establish a comprehensive Makefile for building and managing - Add docker-compose.build.yml for streamlined image construction - Use docker-compose.yml to test built images without a volume --- Dockerfile | 85 ---------------------------------- Makefile | 42 ++++++++++++----- docker-compose.build.yml | 58 +++++++++++++++++++++++ docker-compose.yml | 8 +--- dockerfiles/Dockerfile.bukkit | 71 ++++++++++++++++++++++++++++ dockerfiles/Dockerfile.java | 60 ++++++++++++++++++++++++ dockerfiles/Dockerfile.vanilla | 49 ++++++++++++++++++++ 7 files changed, 269 insertions(+), 104 deletions(-) delete mode 100644 Dockerfile create mode 100644 docker-compose.build.yml create mode 100644 dockerfiles/Dockerfile.bukkit create mode 100644 dockerfiles/Dockerfile.java create mode 100644 dockerfiles/Dockerfile.vanilla diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index e018d7e..0000000 --- a/Dockerfile +++ /dev/null @@ -1,85 +0,0 @@ -FROM debian:stable-slim - -ARG VERSION=latest -ARG JAVA_VERSION=latest -ENV DEBIAN_FRONTEND=noninteractive - -# Create minecraft user -RUN groupadd -g 1000 minecraft && \ - useradd -m -u 1000 -g 1000 -d /app minecraft - -# Install scripting dependencies -RUN apt-get update && \ - apt-get install -y curl gpg jq procps screen strace && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -# Eclipse Adoptium DEB installer package -RUN set -ux && \ - # Download the Eclipse Adoptium GPG key - curl -s https://packages.adoptium.net/artifactory/api/gpg/key/public \ - | gpg --dearmor | tee /etc/apt/trusted.gpg.d/adoptium.gpg > /dev/null && \ - # Configure the Eclipse Adoptium apt repository - VERSION_CODENAME="$(awk -F= '/^VERSION_CODENAME/{print $2}' /etc/os-release)" && \ - echo "deb https://packages.adoptium.net/artifactory/deb $VERSION_CODENAME main" \ - | tee /etc/apt/sources.list.d/adoptium.list - -# Install Adoptium Temurin (OpenJDK Distribution) -RUN set -ux && \ - # Grab latest LTS version if not specified - if [ "$JAVA_VERSION" = "latest" ]; then \ - JAVA_VERSION="$( \ - curl -s https://api.adoptium.net/v3/info/available_releases \ - | jq '.most_recent_lts' \ - )"; \ - fi && \ - # Install the Temurin version - apt-get update && \ - apt-get install -y "temurin-${JAVA_VERSION}-jre" && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -# Download files and run as user -USER minecraft -WORKDIR /app - -# Download and verify sha1sum for server.jar -RUN set -ux && \ - # Grab latest version if not specified - if [ "$VERSION" = "latest" ]; then \ - VERSION="$( \ - curl -s https://launchermeta.mojang.com/mc/game/version_manifest.json \ - | jq -r '.latest.release' \ - )"; \ - fi && \ - # Get server.jar based on $VERSION - curl -s https://launchermeta.mojang.com/mc/game/version_manifest.json \ - | jq -r --arg id "$VERSION" '.versions[] | select(.id == $id) | .url' \ - | xargs curl -s | jq -r '.downloads.server' | tee "/tmp/dl.json" \ - | jq -r '.url' | xargs curl -s -o server.jar && \ - # Get SHA1 hash of server.jar and compare - SHA1="$(sha1sum server.jar | awk '{print $1}')" && \ - EXPECTED="$(jq -r .sha1 /tmp/dl.json)"; rm /tmp/dl.json && \ - if [ ! "$SHA1" = "$EXPECTED" ]; then \ - echo "[ERROR] SHA1=\"$SHA1\" expected \"$EXPECTED\""; \ - exit 1; \ - fi - -# Generate initial settings -RUN java -jar server.jar --initSettings --nogui - -# Back to root to copy the entrypoint in -USER root -WORKDIR /app - -# Copy in entrypoint script -COPY entrypoint.sh /usr/local/bin/entrypoint.sh -RUN chmod +x /usr/local/bin/entrypoint.sh - -# Run app as minecraft user -USER minecraft -WORKDIR /app - -# Expose port and run entrypoint script -EXPOSE 25565 -ENTRYPOINT ["entrypoint.sh"] diff --git a/Makefile b/Makefile index 991f1cd..926ecee 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,35 @@ -CONTAINER = minecraft-minecraft-1 +DOCKER_COMPOSE_BUILD = docker compose -f docker-compose.build.yml build +DOCKER_COMPOSE_UP = docker compose up -d -.PHONY: default build clean install -default: build +PRUNE_IMAGES = \ + localhost/minecraft:latest \ + localhost/minecraft:latest-spigot \ + localhost/minecraft:latest-craftbukkit \ + localhost/minecraft-jre:latest \ + localhost/minecraft-jdk:latest -build: - docker compose build +.PHONY: all clean craftbukkit default install jdk jre spigot vanilla +default: vanilla +all: vanilla spigot craftbukkit + +jre: + $(DOCKER_COMPOSE_BUILD) minecraft-jre + +jdk: + $(DOCKER_COMPOSE_BUILD) minecraft-jdk + +vanilla: jre + $(DOCKER_COMPOSE_BUILD) minecraft-vanilla + +spigot: jre jdk + $(DOCKER_COMPOSE_BUILD) minecraft-spigot + +craftbukkit: jre jdk + $(DOCKER_COMPOSE_BUILD) minecraft-craftbukkit + +install: + $(DOCKER_COMPOSE_UP) clean: - rm -f screenlog.0 - docker compose down --rmi all + docker image rm $(PRUNE_IMAGES) || true docker builder prune -f - -install: build - touch screenlog.0 - docker compose up -d && \ - docker logs -f $(CONTAINER) diff --git a/docker-compose.build.yml b/docker-compose.build.yml new file mode 100644 index 0000000..4336043 --- /dev/null +++ b/docker-compose.build.yml @@ -0,0 +1,58 @@ +services: + minecraft-jre: + build: + context: . + dockerfile: ./dockerfiles/Dockerfile.java + args: + JAVA_VERSION: ${JAVA_VERSION:-latest} + JAVA_RUNTIME: 'true' + image: ${JRE_IMAGE:-localhost/minecraft-jre}:${JRE_TAG:-latest} + + minecraft-jdk: + build: + context: . + dockerfile: ./dockerfiles/Dockerfile.java + args: + JAVA_VERSION: ${JAVA_VERSION:-latest} + JAVA_RUNTIME: 'false' + image: ${JDK_IMAGE:-localhost/minecraft-jdk}:${JDK_TAG:-latest} + + minecraft-vanilla: + build: + context: . + dockerfile: ./dockerfiles/Dockerfile.vanilla + args: + VERSION: ${VERSION:-latest} + image: ${VANILLA_IMAGE:-localhost/minecraft}:${VANILLA_TAG:-latest} + depends_on: + - minecraft-jre + environment: + EULA: "${EULA:-false}" + + minecraft-spigot: + build: + context: . + dockerfile: ./dockerfiles/Dockerfile.bukkit + args: + VERSION: ${MINECRAFT_VERSION:-latest} + SPIGOT: 'true' + image: ${SPIGOT_IMAGE:-localhost/minecraft}:${SPIGOT_TAG:-latest-spigot} + depends_on: + - minecraft-jre + - minecraft-jdk + environment: + EULA: "${EULA:-false}" + + minecraft-craftbukkit: + build: + context: . + dockerfile: ./dockerfiles/Dockerfile.bukkit + args: + VERSION: ${MINECRAFT_VERSION:-latest} + SPIGOT: 'false' + image: ${CRAFTBUKKIT_IMAGE:-localhost/minecraft}:${CRAFTBUKKIT_TAG:-latest-craftbukkit} + depends_on: + - minecraft-jre + - minecraft-jdk + environment: + EULA: "${EULA:-false}" diff --git a/docker-compose.yml b/docker-compose.yml index d827fe0..0fd4bff 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,12 +1,6 @@ services: minecraft: - build: - context: . - dockerfile: Dockerfile - args: - VERSION: ${VERSION:-latest} - JAVA_VERSION: ${JAVA_VERSION:-latest} - image: ${IMAGE:-minecraft}:${TAG:-latest} + image: ${IMAGE:-localhost/minecraft}:${TAG:-latest} ports: - "0.0.0.0:25565:25565" environment: diff --git a/dockerfiles/Dockerfile.bukkit b/dockerfiles/Dockerfile.bukkit new file mode 100644 index 0000000..06e4911 --- /dev/null +++ b/dockerfiles/Dockerfile.bukkit @@ -0,0 +1,71 @@ +# Build from OpenJDK image +FROM "${JDK_IMAGE:-localhost/minecraft-jdk}":"${JDK_TAG:-latest}" as build + +# Minecraft version +ARG VERSION=latest + +# Defaults to building Spigot over CraftBukkit +ARG SPIGOT=true + +# SpigotMC BuildTools URL +ARG BASE_URL="https://hub.spigotmc.org/jenkins/job/BuildTools/" +ARG ARTIFACT_PATH="lastSuccessfulBuild/artifact/target/BuildTools.jar" + +# Build in common container location +WORKDIR /build + +# Download and build Spigot using BuildTools +RUN set -ux && \ +# Grab latest version if not specified + if [ "$VERSION" = "latest" ]; then \ + VERSION="$( \ + curl -s https://launchermeta.mojang.com/mc/game/version_manifest.json \ + | jq -r '.latest.release' \ + )"; \ + fi && \ + # Download BuildTools.jar + curl -s -o BuildTools.jar "${BASE_URL}${ARTIFACT_PATH}" && \ + # Build Craftbukkit if SPIGOT is false + case "$SPIGOT" in \ + true) \ + BUILD_TYPE='SPIGOT' ;; \ + false) \ + BUILD_TYPE='CRAFTBUKKIT' ;; \ + *) \ + echo "ERROR: Invalid value for SPIGOT. Set to 'true' or 'false'"; \ + exit 1 ;; \ + esac && \ + # Run BuildTools to build specified version + java -jar BuildTools.jar --rev "$VERSION" --compile "$BUILD_TYPE" && \ + ln -s \ + "$(echo $BUILD_TYPE | tr '[:upper:]' '[:lower:]')-${VERSION}.jar" \ + "server.jar" + +# Use OpenJRE image for runtime +FROM "${JRE_IMAGE:-localhost/minecraft-jre}":"${JRE_TAG:-latest}" as runtime + +# Run as Minecraft user +USER minecraft +WORKDIR /app + +# Copy the built bukkit jar from the build stage +COPY --from=build /build/server.jar /app/server.jar + +# Generate initial settings +RUN java -jar server.jar --initSettings --nogui + +# Back to root to copy the entrypoint in +USER root +WORKDIR /app + +# Copy in entrypoint script +COPY ../entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +# Run app as minecraft user +USER minecraft +WORKDIR /app + +# Expose port and run entrypoint script +EXPOSE 25565 +ENTRYPOINT ["entrypoint.sh"] diff --git a/dockerfiles/Dockerfile.java b/dockerfiles/Dockerfile.java new file mode 100644 index 0000000..5d563b1 --- /dev/null +++ b/dockerfiles/Dockerfile.java @@ -0,0 +1,60 @@ +FROM debian:stable-slim + +ARG JAVA_RUNTIME +ARG JAVA_VERSION=latest +ENV DEBIAN_FRONTEND=noninteractive + +# Install scripting dependencies +RUN apt-get update && \ + apt-get install -y curl git gpg jq && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Eclipse Adoptium DEB installer package +RUN set -ux && \ + # Download the Eclipse Adoptium GPG key + curl -s https://packages.adoptium.net/artifactory/api/gpg/key/public \ + | gpg --dearmor | tee /etc/apt/trusted.gpg.d/adoptium.gpg > /dev/null && \ + # Configure the Eclipse Adoptium APT repository + VERSION_CODENAME="$(awk -F= '/^VERSION_CODENAME/{print $2}' /etc/os-release)" && \ + echo "deb https://packages.adoptium.net/artifactory/deb $VERSION_CODENAME main" \ + | tee /etc/apt/sources.list.d/adoptium.list + +# Install Adoptium Temurin (OpenJDK/OpenJRE) +RUN set -ux && \ + # Grab latest LTS version if not specified + if [ "$JAVA_VERSION" = "latest" ]; then \ + JAVA_VERSION="$( \ + curl -s https://api.adoptium.net/v3/info/available_releases \ + | jq '.most_recent_lts' \ + )"; \ + fi && \ + # Install OpenJDK if JAVA_RUNTIME is false + case "$JAVA_RUNTIME" in \ + true) \ + JAVA_TYPE='jre' ;; \ + false) \ + JAVA_TYPE='jdk' ;; \ + *) \ + echo "ERROR: Invalid value for JAVA_RUNTIME. Set to 'true' or 'false'"; \ + exit 1 ;; \ + esac && \ + # Install the Temurin version + apt-get update && \ + apt-get install -y "temurin-$JAVA_VERSION-$JAVA_TYPE" && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Create minecraft user for runtime +RUN if [ "$JAVA_RUNTIME" = "true" ]; then \ + groupadd -g 1000 minecraft && \ + useradd -m -u 1000 -g 1000 -d /app minecraft; \ + fi + +# Install additional runtime dependencies +RUN if [ "$JAVA_RUNTIME" = "true" ]; then \ + apt-get update && \ + apt-get install -y procps screen strace && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/*; \ + fi diff --git a/dockerfiles/Dockerfile.vanilla b/dockerfiles/Dockerfile.vanilla new file mode 100644 index 0000000..da00840 --- /dev/null +++ b/dockerfiles/Dockerfile.vanilla @@ -0,0 +1,49 @@ +FROM "${JRE_IMAGE:-localhost/minecraft-jre}":"${JRE_TAG:-latest}" + +# Minecraft version to download +ARG VERSION=latest + +# Download files and run as user +USER minecraft +WORKDIR /app + +# Download and verify sha1sum for server.jar +RUN set -ux && \ +# Grab latest version if not specified + if [ "$VERSION" = "latest" ]; then \ + VERSION="$( \ + curl -s https://launchermeta.mojang.com/mc/game/version_manifest.json \ + | jq -r '.latest.release' \ + )"; \ + fi && \ + # Get server.jar based on $VERSION + curl -s https://launchermeta.mojang.com/mc/game/version_manifest.json \ + | jq -r --arg id "$VERSION" '.versions[] | select(.id == $id) | .url' \ + | xargs curl -s | jq -r '.downloads.server' | tee "/tmp/dl.json" \ + | jq -r '.url' | xargs curl -s -o server.jar && \ + # Get SHA1 hash of server.jar and compare + SHA1="$(sha1sum server.jar | awk '{print $1}')" && \ + EXPECTED="$(jq -r .sha1 /tmp/dl.json)"; rm /tmp/dl.json && \ + if [ ! "$SHA1" = "$EXPECTED" ]; then \ + echo "[ERROR] SHA1=\"$SHA1\" expected \"$EXPECTED\""; \ + exit 1; \ + fi + +# Generate initial settings +RUN java -jar server.jar --initSettings --nogui + +# Back to root to copy the entrypoint in +USER root +WORKDIR /app + +# Copy in entrypoint script +COPY ../entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +# Run app as minecraft user +USER minecraft +WORKDIR /app + +# Expose port and run entrypoint script +EXPOSE 25565 +ENTRYPOINT ["entrypoint.sh"]