diff --git a/.github/workflows/build-multiarch.yml b/.github/workflows/build-multiarch.yml index bcc21354..ea6c3181 100644 --- a/.github/workflows/build-multiarch.yml +++ b/.github/workflows/build-multiarch.yml @@ -20,8 +20,11 @@ on: - "docs/**" - "examples/**" +env: + IMAGE_TO_TEST: itzg/minecraft-server:test-${{ github.repository_owner }}-${{ github.run_id }} + jobs: - docker-buildx: + build: if: github.repository == 'itzg/docker-minecraft-server' runs-on: ubuntu-20.04 steps: @@ -43,14 +46,6 @@ jobs: - name: Setup Docker Buildx uses: docker/setup-buildx-action@v1 - - name: Cache Docker layers - uses: actions/cache@v2.1.7 - with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-buildx-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-buildx- - - name: Set up QEMU uses: docker/setup-qemu-action@v1.2.0 @@ -60,6 +55,26 @@ jobs: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASSWORD }} + - name: Build for test + uses: docker/build-push-action@v2.7.0 + if: github.ref_name == 'master' + with: + context: . + platforms: linux/amd64 + tags: ${{ env.IMAGE_TO_TEST }} + # ensure latest base image is used + pull: true + load: true + push: false + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Run tests + # It is assumed that image variants are merged from master and tested there + if: github.ref_name == 'master' + run: | + tests/test.sh + - name: Build and push id: docker_build uses: docker/build-push-action@v2.7.0 @@ -70,17 +85,9 @@ jobs: tags: ${{ steps.meta.outputs.tags }} # ensure latest base image is used pull: true - cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache-new + cache-from: type=gha + cache-to: type=gha,mode=max labels: ${{ steps.meta.outputs.labels }} - name: Image digest run: echo ${{ steps.docker_build.outputs.digest }} - - - # Temp fix - # https://github.com/docker/build-push-action/issues/252 - # https://github.com/moby/buildkit/issues/1896 - name: Move cache - run: | - rm -rf /tmp/.buildx-cache - mv /tmp/.buildx-cache-new /tmp/.buildx-cache \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0f43c66d..14c1cafd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,6 +15,9 @@ on: - "[0-9]+.[0-9]+.[0-9]+-openj9-nightly" - "[0-9]+.[0-9]+.[0-9]+-adopt11" +env: + IMAGE_TO_TEST: itzg/minecraft-server:test-${{ github.repository_owner }}-${{ github.run_id }} + jobs: test: runs-on: ubuntu-20.04 @@ -54,20 +57,31 @@ jobs: - name: Setup Docker Buildx uses: docker/setup-buildx-action@v1 - - name: Cache Docker layers - uses: actions/cache@v2.1.7 - with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-buildx-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-buildx- - - name: Login to DockerHub uses: docker/login-action@v1 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASSWORD }} + - name: Build for test + uses: docker/build-push-action@v2.7.0 + if: github.ref_name == 'master' + with: + context: . + platforms: linux/amd64 + tags: ${{ env.IMAGE_TO_TEST }} + # ensure latest base image is used + pull: true + load: true + push: false + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Run tests + if: github.ref_name == 'master' + run: | + tests/test.sh + - name: Build and push id: docker_build uses: docker/build-push-action@v2.7.0 @@ -80,8 +94,8 @@ jobs: push: true # tags determined by prep step tags: ${{ steps.prep.outputs.tags }} - cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache-new + cache-from: type=gha + cache-to: type=gha,mode=max labels: | org.opencontainers.image.documentation=https://github.com/itzg/docker-minecraft-server org.opencontainers.image.version=${{ steps.prep.outputs.version }} @@ -90,11 +104,3 @@ jobs: - name: Image digest run: echo ${{ steps.docker_build.outputs.digest }} - - - # Temp fix - # https://github.com/docker/build-push-action/issues/252 - # https://github.com/moby/buildkit/issues/1896 - name: Move cache - run: | - rm -rf /tmp/.buildx-cache - mv /tmp/.buildx-cache-new /tmp/.buildx-cache diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 0bcd9c96..c619ca43 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -4,6 +4,9 @@ on: pull_request: branches: [ master ] +env: + IMAGE_TO_TEST: itzg/minecraft-server:test-${{ github.repository_owner }}-${{ github.run_id }} + jobs: test: runs-on: ubuntu-latest @@ -11,6 +14,19 @@ jobs: steps: - uses: actions/checkout@v2.4.0 + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Build + uses: docker/build-push-action@v2.7.0 + with: + context: . + platforms: linux/amd64 + tags: ${{ env.IMAGE_TO_TEST }} + load: true + cache-from: type=gha + cache-to: type=gha,mode=max + - name: Run tests run: | tests/test.sh diff --git a/README.md b/README.md index 8ccee2a1..4f06faf6 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ By default, the container will download the latest version of the "vanilla" [Min * [Troubleshooting](#troubleshooting) * [Server types](#server-types) * [Running a Forge Server](#running-a-forge-server) + * [Running a Fabric Server](#running-a-fabric-server) * [Running a Bukkit/Spigot server](#running-a-bukkitspigot-server) * [Running a Paper server](#running-a-paper-server) * [Running an Airplane server](#running-an-airplane-server) @@ -50,7 +51,6 @@ By default, the container will download the latest version of the "vanilla" [Min * [Running a Catserver type server](#running-a-catserver-type-server) * [Running a Canyon server](#running-a-canyon-server) * [Running a SpongeVanilla server](#running-a-spongevanilla-server) - * [Running a Fabric Server](#running-a-fabric-server) * [Running a Limbo server](#running-a-limbo-server) * [Running a Crucible server](#running-a-crucible-server) * [Running a server with a Feed the Beast modpack](#running-a-server-with-a-feed-the-beast-modpack) @@ -61,10 +61,11 @@ By default, the container will download the latest version of the "vanilla" [Min * [Modpack data directory](#modpack-data-directory) * [Buggy start scripts](#buggy-start-scripts) * [Fixing "unable to launch forgemodloader"](#fixing-unable-to-launch-forgemodloader) + * [Running a server with a packwiz modpack](#running-a-server-with-a-packwiz-modpack) * [Working with mods and plugins](#working-with-mods-and-plugins) * [Optional plugins, mods, and config attach points](#optional-plugins-mods-and-config-attach-points) * [Auto-downloading SpigotMC/Bukkit/PaperMC plugins](#auto-downloading-spigotmcbukkitpapermc-plugins) - * [Downloadable mod/plugin pack for Forge, Bukkit, and Spigot Servers](#downloadable-modplugin-pack-for-forge-bukkit-and-spigot-servers) + * [Downloadable mod/plugin pack for Forge, Fabric, and Bukkit-like Servers](#downloadable-modplugin-pack-for-forge-fabric-and-bukkit-like-servers) * [Generic pack file](#generic-pack-file) * [Mod/Plugin URL Listing File](#modplugin-url-listing-file) * [Remove old mods/plugins](#remove-old-modsplugins) @@ -133,7 +134,7 @@ By default, the container will download the latest version of the "vanilla" [Min * [Running on RaspberryPi](#running-on-raspberrypi) * [Contributing](#contributing) - + @@ -402,6 +403,30 @@ the URL with `FORGE_INSTALLER_URL`, such as: In both of the cases above, there is no need for the `VERSION` or `FORGEVERSION` variables. +### Running a Fabric Server + +Enable [Fabric server](https://fabricmc.net/) mode by adding a `-e TYPE=FABRIC` to your command-line. By default, the container will install the latest [fabric-loader](https://fabricmc.net/wiki/documentation:fabric_loader) using the latest [fabric-installer](https://fabricmc.net/use/), against the minecraft server version you have defined with `VERSION` (defaulting to the latest vanilla release of the game). + +``` +docker run -d -v /path/on/host:/data \ + -e TYPE=FABRIC \ + -p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server +``` + +See the [Working with mods and plugins](#working-with-mods-and-plugins) section to set up Fabric mods and configuration. + +A specific loader version other than the latest can be requested using `FABRIC_LOADER_VERSION`, such as: + +``` +docker run -d -v /path/on/host:/data ... \ + -e FABRIC_LOADER_VERSION=0.12.8 +``` + +If you wish to use an alternative installer you can: +* Specify an alternative version using `FABRIC_INSTALLER_VERSION` (such as `-e FABRIC_INSTALLER_VERSION=0.10.2`) +* Provide the path to a custom installer jar available to the container with `FABRIC_INSTALLER`, relative to `/data` (such as `-e FABRIC_INSTALLER=fabric-installer-0.5.0.32.jar`) +* Provide the URL to a custom installer jar with `FABRIC_INSTALLER_URL` (such as `-e FABRIC_INSTALLER_URL=http://HOST/fabric-installer-0.5.0.32.jar`) + ### Running a Bukkit/Spigot server Enable Bukkit/Spigot server mode by adding a `-e TYPE=BUKKIT` or `-e TYPE=SPIGOT` to your command-line. @@ -532,39 +557,6 @@ Just change it with `SPONGEBRANCH`, such as: $ docker run -d -v /path/on/host:/data ... \ -e TYPE=SPONGEVANILLA -e SPONGEBRANCH=EXPERIMENTAL ... -### Running a Fabric Server - -Enable [Fabric server](http://fabricmc.net/use/) mode by adding a `-e TYPE=FABRIC` to your command-line. By default, the container will run the latest version, but you can also choose to run a specific version with `VERSION`. - -``` -docker run -d -v /path/on/host:/data \ - -e TYPE=FABRIC \ - -p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server -``` - -A specific installer version can be requested using `FABRIC_INSTALLER_VERSION`. - -To use a pre-downloaded Fabric installer, place it in a directory attached into the container, such as the `/data` volume and specify the name of the installer file with `FABRIC_INSTALLER`, such as: - -``` -docker run -d -v /path/on/host:/data ... \ - -e FABRIC_INSTALLER=fabric-installer-0.5.0.32.jar ... -``` - -To download a Fabric installer from a custom location, such as your own file repository, specify the URL with `FABRIC_INSTALLER_URL`, such as: - -``` -docker run -d -v /path/on/host:/data ... \ - -e FABRIC_INSTALLER_URL=http://HOST/fabric-installer-0.5.0.32.jar ... -``` - -A specific loader version can be requested using `FABRIC_LOADER_VERSION`, such as: - -``` -docker run -d -v /path/on/host:/data ... \ - -e FABRIC_LOADER_VERSION=0.11.7 -``` - ### Running a Limbo server A [Limbo](https://github.com/LOOHP/Limbo) server can be run by setting `TYPE` to `LIMBO`. @@ -660,6 +652,20 @@ then you apply a workaround by adding this to the run invocation: -e FTB_LEGACYJAVAFIXER=true +## Running a server with a packwiz modpack + +[packwiz](https://packwiz.infra.link/) is a CLI tool for maintaining and providing modpack definitions, with support for both CurseForge and Modrinth as sources. See the [packwiz tutorial](https://packwiz.infra.link/tutorials/getting-started/) for more information. + +To configure server mods using a packwiz modpack, set the `PACKWIZ_URL` environment variable to the location of your `pack.toml` modpack definition: + + docker run -d -v /path/on/host:/data -e TYPE=FABRIC \ + -e "PACKWIZ_URL=https://example.com/modpack/pack.toml" \ + itzg/minecraft-server + +packwiz modpack defitions are processed before other mod definitions (`MODPACK`, `MODS`, etc.) to allow for additional processing/overrides you may want to perform (in case of mods not available via Modrinth/CurseForge, or you do not maintain the pack). + +> packwiz is pre-configured to only download server mods. If client-side mods are downloaded and cause issues, check your pack.toml configuration, and make sure any client-only mods are not set to `"both"`, but rather `"client"` for the side configuration item. + ## Working with mods and plugins ### Optional plugins, mods, and config attach points @@ -670,7 +676,7 @@ There are optional volume paths that can be attached to supply content to be cop : contents are synchronized into `/data/plugins` for Bukkit related server types. Set `SYNC_SKIP_NEWER_IN_DESTINATION=false` if you want files from `/plugins` to take precedence over newer files in `/data/plugins`. `/mods` -: contents are synchronized into `/data/mods` for Forge related server types. The destination can be changed by setting `COPY_MODS_DEST`. +: contents are synchronized into `/data/mods` for Fabric and Forge related server types. The destination can be changed by setting `COPY_MODS_DEST`. `/config` : contents are synchronized into `/data/config` by default, but can be changed with `COPY_CONFIG_DEST`. 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. Set `SYNC_SKIP_NEWER_IN_DESTINATION=false` if you want files from `/config` to take precedence over newer files in `/data/config`. @@ -683,7 +689,7 @@ For example: `-e REMOVE_OLD_MODS=TRUE -e REMOVE_OLD_MODS_INCLUDE="*.jar" -e REMO These paths work 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. -> For more flexibility with mods/plugins preparation, you can declare directories to use in [the `MODS` variable](#downloadable-modplugin-pack-for-forge-bukkit-and-spigot-servers) +> For more flexibility with mods/plugins preparation, you can declare directories to use in [the `MODS` variable](#downloadable-modplugin-pack-for-forge-fabric-and-bukkit-like-servers) ### Auto-downloading SpigotMC/Bukkit/PaperMC plugins @@ -700,10 +706,10 @@ For example, the following will auto-download the [EssentialsX](https://www.spig -e SPIGET_RESOURCES=9089,34315 -### Downloadable mod/plugin pack for Forge, Bukkit, and Spigot Servers +### Downloadable mod/plugin pack for Forge, Fabric, and Bukkit-like Servers Like the `WORLD` option above, you can specify the URL or path 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/Fabric 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 ... diff --git a/scripts/start-deployPurpur b/scripts/start-deployPurpur index 37ea2567..cc1233f5 100755 --- a/scripts/start-deployPurpur +++ b/scripts/start-deployPurpur @@ -10,7 +10,7 @@ isDebugging && set -x : ${FORCE_REDOWNLOAD:=false} if [[ ${PURPUR_BUILD} == LATEST ]]; then - PURPUR_BUILD=$(curl -fsSL "https://api.pl3x.net/v2/purpur/${VANILLA_VERSION}" | + PURPUR_BUILD=$(curl -fsSL "https://api.purpurmc.org/v2/purpur/${VANILLA_VERSION}" | jq -r '.builds.latest' || echo "") if [[ -z ${PURPUR_BUILD} ]]; then log "ERROR: Failed to locate a Purpur build for ${VANILLA_VERSION}." @@ -22,7 +22,7 @@ fi export SERVER="purpur-${VANILLA_VERSION}-${PURPUR_BUILD}.jar" if [ ! -f "$SERVER" ] || isTrue "$FORCE_REDOWNLOAD"; then - downloadUrl="https://api.pl3x.net/v2/purpur/${VANILLA_VERSION}/${PURPUR_BUILD}/download" + downloadUrl="https://api.purpurmc.org/v2/purpur/${VANILLA_VERSION}/${PURPUR_BUILD}/download" log "Downloading Purpur from $downloadUrl ..." if ! curl -fsSL -o "$SERVER" "$downloadUrl"; then log "ERROR: failed to download from $downloadUrl (status=$?)" diff --git a/scripts/start-setupModpack b/scripts/start-setupModpack index 18605299..02036b46 100755 --- a/scripts/start-setupModpack +++ b/scripts/start-setupModpack @@ -20,6 +20,33 @@ if isTrue "${REMOVE_OLD_MODS}" && [ -z "${MODS_FILE}" ]; then removeOldMods /data/plugins fi +# If packwiz url passed, bootstrap packwiz and update mods before other modpack processing +if [[ "${PACKWIZ_URL}" ]]; then + # Ensure we have the latest packwiz bootstrap installer + latestPackwiz=$(curl -fsSL https://api.github.com/repos/comp500/packwiz-installer-bootstrap/releases/latest) + if [[ -z "${latestPackwiz}" ]]; then + log "WARNING: Could not retrieve Packwiz bootstrap installer release information" + else + isDebugging && log "Latest packwiz ${latestPackWiz}" + latestPackwizVer=$(echo ${latestPackwiz} | jq --raw-output '.tag_name') + latestPackwizUrl=$(echo ${latestPackwiz} | jq --raw-output '.assets[] | select(.name | match("packwiz-installer-bootstrap.jar")) | .url') + : "${PACKWIZ_JAR:=packwiz-installer-bootstrap_${latestPackwizVer}.jar}" + if [[ ! -e $PACKWIZ_JAR ]]; then + log "Downloading Packwiz ${latestPackwizVer}" + curl -H "Accept:application/octet-stream" -o "$PACKWIZ_JAR" -fsSL ${latestPackwizUrl} + ln -sf "${PACKWIZ_JAR}" packwiz-installer-bootstrap.jar + fi + fi + if [[ ! -e packwiz-installer-bootstrap.jar ]]; then + log "ERROR: Packwiz not available or could not be downloaded from Github!" + exit 1 + fi + if isURL "${PACKWIZ_URL}"; then + log "Running packwiz against URL: ${PACKWIZ_URL}" + java -jar packwiz-installer-bootstrap.jar -g -s server "${PACKWIZ_URL}" + fi +fi + # If supplied with a URL for a modpack (simple zip of jars), download it and unpack if [[ "$MODPACK" ]]; then if isURL "${MODPACK}"; then diff --git a/tests/docker-compose.test.yml b/tests/docker-compose.test.yml index bc6fc775..1638b74b 100644 --- a/tests/docker-compose.test.yml +++ b/tests/docker-compose.test.yml @@ -1,20 +1,14 @@ version: "3.8" services: - sut: + monitor: depends_on: - mc - image: itzg/mc-monitor:0.6.0 - command: status --host mc --retry-interval 1s --retry-limit 120 + image: itzg/mc-monitor:${MC_MONITOR_VERSION:-0.10.4} + command: --debug status --host mc --retry-interval 1s --retry-limit 240 mc: restart: "no" - build: - context: .. - args: - TARGETOS: linux - TARGETARCH: amd64 - cache_from: - - itzg/minecraft-server:latest + image: ${IMAGE_TO_TEST:-itzg/minecraft-server} environment: EULA: "TRUE" diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml new file mode 100644 index 00000000..63b75fc0 --- /dev/null +++ b/tests/docker-compose.yml @@ -0,0 +1,14 @@ +version: "3.8" + +services: + monitor: + depends_on: + - mc + image: itzg/mc-monitor:${MC_MONITOR_VERSION:-0.10.4} + command: status --host mc --retry-interval 1s --timeout 1s --retry-limit 240 + mc: + restart: "no" + image: ${IMAGE_TO_TEST:-itzg/minecraft-server} + environment: + EULA: "TRUE" + diff --git a/tests/test.sh b/tests/test.sh index 376aed99..9db35dec 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -1,17 +1,22 @@ #!/bin/bash -cd $(dirname $0) +cd "$(dirname "$0")" || exit 1 failed=false -args="-f docker-compose.test.yml" -docker-compose $args run sut || failed=true + +down() { + docker-compose down -v +} + +docker-compose run monitor || failed=true echo " Result: failed=$failed" -$failed && docker-compose $args logs mc -docker-compose $args down -v - if $failed; then + docker-compose logs mc + down exit 1 +else + down fi