Compare commits

..

1 Commits

Author SHA1 Message Date
Geoff Bourne f502acfbff build: fix regex pattern that was bad in docs 2026-02-16 12:06:30 -06:00
68 changed files with 299 additions and 1048 deletions
-6
View File
@@ -13,15 +13,9 @@ updates:
- minor - minor
- package-ecosystem: pip - package-ecosystem: pip
directory: "/docs" directory: "/docs"
labels:
- dependencies
- documentation
schedule: schedule:
interval: weekly interval: weekly
groups: groups:
docker:
patterns:
- "docker/*"
patches: patches:
patterns: patterns:
- "*" - "*"
-1
View File
@@ -2,7 +2,6 @@ changelog:
exclude: exclude:
authors: authors:
- dependabot - dependabot
- renovate
categories: categories:
- title: Enhancements - title: Enhancements
labels: labels:
+15 -24
View File
@@ -27,7 +27,6 @@ jobs:
# NOTE: the "latest" variant is identified in the Docker meta step's 'latest' config # NOTE: the "latest" variant is identified in the Docker meta step's 'latest' config
variant: variant:
- java25 - java25
- java25-alpine
- java25-jdk - java25-jdk
- java21 - java21
- java21-alpine - java21-alpine
@@ -43,10 +42,6 @@ jobs:
baseImage: eclipse-temurin:25-jre baseImage: eclipse-temurin:25-jre
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
mcVersion: latest mcVersion: latest
- variant: java25-alpine
baseImage: eclipse-temurin:25-jre-alpine
platforms: linux/amd64,linux/arm64
mcVersion: latest
- variant: java25-jdk - variant: java25-jdk
baseImage: eclipse-temurin:25 baseImage: eclipse-temurin:25
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
@@ -55,15 +50,15 @@ jobs:
- variant: java21 - variant: java21
baseImage: eclipse-temurin:21-jre baseImage: eclipse-temurin:21-jre
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
mcVersion: 1.21.11 mcVersion: latest
- variant: java21-jdk - variant: java21-jdk
baseImage: eclipse-temurin:21 baseImage: eclipse-temurin:21
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
mcVersion: 1.21.11 mcVersion: latest
- variant: java21-alpine - variant: java21-alpine
baseImage: eclipse-temurin:21-jre-alpine baseImage: eclipse-temurin:21-jre-alpine
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
mcVersion: 1.21.11 mcVersion: latest
# JAVA 17: # JAVA 17:
- variant: java17 - variant: java17
# jammy doesn't work until minecraft updates to https://github.com/netty/netty/issues/12343 # jammy doesn't work until minecraft updates to https://github.com/netty/netty/issues/12343
@@ -75,28 +70,24 @@ jobs:
baseImage: adoptopenjdk:16-jre-hotspot baseImage: adoptopenjdk:16-jre-hotspot
platforms: linux/amd64,linux/arm/v7,linux/arm64 platforms: linux/amd64,linux/arm/v7,linux/arm64
mcVersion: 1.16.5 mcVersion: 1.16.5
# Pin version for pre-Java 17
mcHelperVersion: 1.51.3-java8
# JAVA 11 # JAVA 11
- variant: java11 - variant: java11
baseImage: adoptopenjdk:11-jre-hotspot baseImage: adoptopenjdk:11-jre-hotspot
platforms: linux/amd64,linux/arm/v7,linux/arm64 platforms: linux/amd64,linux/arm/v7,linux/arm64
mcVersion: 1.16.4 mcVersion: 1.16.4
# Pin version for pre-Java 17
mcHelperVersion: 1.51.3-java8
# JAVA 8: NOTE: Unable to go past 8u312 because of Forge dependencies # JAVA 8: NOTE: Unable to go past 8u312 because of Forge dependencies
- variant: java8 - variant: java8
baseImage: eclipse-temurin:8u312-b07-jre-focal baseImage: eclipse-temurin:8u312-b07-jre-focal
platforms: linux/amd64,linux/arm/v7,linux/arm64 platforms: linux/amd64,linux/arm/v7,linux/arm64
mcVersion: 1.12.2 mcVersion: 1.12.2
# Pin version for Java 8, also be sure to set in verify-pr.yml # Pin version for Java 8
mcHelperVersion: 1.51.3-java8 mcHelperVersion: 1.51.1
- variant: java8-jdk - variant: java8-jdk
baseImage: eclipse-temurin:8u312-b07-jdk-focal baseImage: eclipse-temurin:8u312-b07-jdk-focal
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
mcVersion: 1.12.2 mcVersion: 1.12.2
# Pin version for Java 8, also be sure to set in verify-pr.yml # Pin version for Java 8
mcHelperVersion: 1.51.3-java8 mcHelperVersion: 1.51.1
env: env:
IMAGE_TO_TEST: "${{ github.repository_owner }}/minecraft-server:test-${{ matrix.variant }}-${{ github.run_id }}" IMAGE_TO_TEST: "${{ github.repository_owner }}/minecraft-server:test-${{ matrix.variant }}-${{ github.run_id }}"
HAS_IMAGE_REPO_ACCESS: ${{ secrets.DOCKER_USER != '' && secrets.DOCKER_PASSWORD != '' }} HAS_IMAGE_REPO_ACCESS: ${{ secrets.DOCKER_USER != '' && secrets.DOCKER_PASSWORD != '' }}
@@ -104,14 +95,14 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v7 uses: actions/checkout@v6.0.2
with: with:
# for build-files step # for build-files step
fetch-depth: 0 fetch-depth: 0
- name: Docker meta - name: Docker meta
id: meta id: meta
uses: docker/metadata-action@v6.1.0 uses: docker/metadata-action@v5.10.0
with: with:
# NOTE for forks: if your Docker Hub organization doesn't match your Github repo's, # NOTE for forks: if your Docker Hub organization doesn't match your Github repo's,
# then the use of ${{ github.repository_owner }} will need to be replaced. # then the use of ${{ github.repository_owner }} will need to be replaced.
@@ -141,13 +132,13 @@ jobs:
org.opencontainers.image.authors=Geoff Bourne <itzgeoff@gmail.com> org.opencontainers.image.authors=Geoff Bourne <itzgeoff@gmail.com>
- name: Setup Docker Buildx - name: Setup Docker Buildx
uses: docker/setup-buildx-action@v4 uses: docker/setup-buildx-action@v3.12.0
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v4.1.0 uses: docker/setup-qemu-action@v3.7.0
- name: Build for test - name: Build for test
uses: docker/build-push-action@v7 uses: docker/build-push-action@v6.19.2
with: with:
platforms: linux/amd64 platforms: linux/amd64
tags: ${{ env.IMAGE_TO_TEST }} tags: ${{ env.IMAGE_TO_TEST }}
@@ -172,14 +163,14 @@ jobs:
tests/test.sh tests/test.sh
- name: Login to DockerHub - name: Login to DockerHub
uses: docker/login-action@v4.2.0 uses: docker/login-action@v3.7.0
if: env.HAS_IMAGE_REPO_ACCESS if: env.HAS_IMAGE_REPO_ACCESS
with: with:
username: ${{ secrets.DOCKER_USER }} username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GHCR - name: Login to GHCR
uses: docker/login-action@v4.2.0 uses: docker/login-action@v3.7.0
if: env.HAS_IMAGE_REPO_ACCESS if: env.HAS_IMAGE_REPO_ACCESS
with: with:
registry: ghcr.io registry: ghcr.io
@@ -187,7 +178,7 @@ jobs:
password: ${{ github.token }} password: ${{ github.token }}
- name: Build and push - name: Build and push
uses: docker/build-push-action@v7 uses: docker/build-push-action@v6.19.2
if: github.actor == github.repository_owner if: github.actor == github.repository_owner
with: with:
platforms: ${{ matrix.platforms }} platforms: ${{ matrix.platforms }}
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
steps: steps:
- name: on-publish - name: on-publish
if: github.event_name == 'release' && github.event.action == 'published' if: github.event_name == 'release' && github.event.action == 'published'
uses: SethCohen/github-releases-to-discord@v1.20.0 uses: SethCohen/github-releases-to-discord@v1.19.0
with: with:
webhook_url: ${{ secrets.DISCORD_WEBHOOK }} webhook_url: ${{ secrets.DISCORD_WEBHOOK }}
- name: on-success - name: on-success
+28 -12
View File
@@ -1,17 +1,33 @@
name: Issues notify name: Issue labels
on: on:
issues: issues:
types: types: [labeled, reopened, closed, deleted]
- opened
- labeled env:
- unlabeled DISCORD_WEBHOOK: ${{ secrets.DISCORD_ISSUES_WEBHOOK }}
- closed
jobs: jobs:
notify: labelNotify:
uses: itzg/github-workflows/.github/workflows/issues-notify-discord.yml@main runs-on: ubuntu-latest
with: timeout-minutes: 5
triageLabel: 'status/needs triage' steps:
secrets: - name: notify on label
discordWebhook: "${{secrets.DISCORD_ISSUES_WEBHOOK}}" if: >
github.event.label.name == 'enhancement'
|| github.event.label.name == 'bug'
|| github.event.label.name == 'help wanted'
|| github.event.label.name == 'priority/high'
|| github.event.label.name == 'question'
|| github.event.label.name == 'status/waiting on upstream'
uses: Ilshidur/action-discord@master
with:
args: "[${{ github.event.issue.title }} (#${{ github.event.issue.number }})](<${{ github.event.issue.html_url }}>) added `${{ github.event.label.name }}` label"
- name: notify on action change
if: >
github.event.action == 'closed'
|| github.event.action == 'reopened'
|| github.event.action == 'deleted'
uses: Ilshidur/action-discord@master
with:
args: "[${{ github.event.issue.title }} (#${{ github.event.issue.number }})](<${{ github.event.issue.html_url }}>) has been `${{ github.event.action }}` by `${{ github.event.sender.login }}`"
-16
View File
@@ -1,16 +0,0 @@
name: Sponsor Labeler
on:
issues:
types:
- opened
pull_request_target:
types:
- opened
jobs:
label-sponsor:
uses: itzg/github-workflows/.github/workflows/sponsor-labeler.yml@main
with:
author: ${{ github.event.issue.user.login || github.event.pull_request.user.login }}
number: ${{ github.event.issue.number || github.event.pull_request.number }}
-35
View File
@@ -1,35 +0,0 @@
name: Verify Docs
on:
pull_request:
paths:
- 'docs/**'
- 'zensical.toml'
- '.github/workflows/verify-docs.yml'
workflow_dispatch:
jobs:
verify:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Build docs image
uses: docker/build-push-action@v7
with:
context: .
file: docs/Dockerfile
load: true
tags: docs-verifier:latest
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Verify rendering
run: |
docker run --rm \
-v ${{ github.workspace }}:/docs \
docs-verifier:latest build --strict
+9 -9
View File
@@ -23,7 +23,7 @@ jobs:
matrix: matrix:
variant: variant:
- java25 - java25
- java25-alpine - java21-alpine
- java17 - java17
- java8 - java8
include: include:
@@ -32,8 +32,8 @@ jobs:
baseImage: eclipse-temurin:25-jre baseImage: eclipse-temurin:25-jre
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
mcVersion: latest mcVersion: latest
- variant: java25-alpine - variant: java21-alpine
baseImage: eclipse-temurin:25-jre-alpine baseImage: eclipse-temurin:21-jre-alpine
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
mcVersion: latest mcVersion: latest
# JAVA 17: # JAVA 17:
@@ -46,23 +46,23 @@ jobs:
baseImage: eclipse-temurin:8u312-b07-jre-focal baseImage: eclipse-temurin:8u312-b07-jre-focal
platforms: linux/amd64 platforms: linux/amd64
mcVersion: 1.12.2 mcVersion: 1.12.2
# Pin version for Java 8, be sure to also set in build.yml # Pin version for Java 8
mcHelperVersion: 1.51.3-java8 mcHelperVersion: 1.51.1
env: env:
IMAGE_TO_TEST: ${{ github.repository_owner }}/minecraft-server:test-${{ matrix.variant }}-${{ github.run_id }} IMAGE_TO_TEST: ${{ github.repository_owner }}/minecraft-server:test-${{ matrix.variant }}-${{ github.run_id }}
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v7 uses: actions/checkout@v6.0.2
with: with:
# for build-files step # for build-files step
fetch-depth: 0 fetch-depth: 0
- name: Setup Docker Buildx - name: Setup Docker Buildx
uses: docker/setup-buildx-action@v4 uses: docker/setup-buildx-action@v3.12.0
- name: Confirm multi-arch build - name: Confirm multi-arch build
uses: docker/build-push-action@v7 uses: docker/build-push-action@v6.19.2
with: with:
platforms: ${{ matrix.platforms }} platforms: ${{ matrix.platforms }}
# ensure latest base image is used # ensure latest base image is used
@@ -73,7 +73,7 @@ jobs:
cache-from: type=gha,scope=${{ matrix.variant }} cache-from: type=gha,scope=${{ matrix.variant }}
- name: Build for test - name: Build for test
uses: docker/build-push-action@v7 uses: docker/build-push-action@v6.19.2
with: with:
# Only build single platform since loading multi-arch image into daemon fails with # Only build single platform since loading multi-arch image into daemon fails with
# "docker exporter does not currently support exporting manifest lists" # "docker exporter does not currently support exporting manifest lists"
+6 -2
View File
@@ -1,15 +1,19 @@
version: 2 version: 2
python:
install:
- requirements: docs/requirements.txt
build: build:
os: ubuntu-24.04 os: ubuntu-24.04
tools: tools:
python: "3.14" python: latest
jobs: jobs:
# We recommend using a requirements file for reproducible builds. # We recommend using a requirements file for reproducible builds.
# This is just a quick example to get started. # This is just a quick example to get started.
# https://docs.readthedocs.io/page/guides/reproducible-builds.html # https://docs.readthedocs.io/page/guides/reproducible-builds.html
install: install:
- pip install -r docs/requirements.txt - pip install zensical
build: build:
html: html:
- zensical build - zensical build
+6 -11
View File
@@ -25,37 +25,32 @@ EXPOSE 25565
ARG APPS_REV=1 ARG APPS_REV=1
ARG GITHUB_BASEURL=https://github.com ARG GITHUB_BASEURL=https://github.com
# renovate: datasource=github-releases packageName=itzg/easy-add ARG EASY_ADD_VERSION=0.8.11
ARG EASY_ADD_VERSION=0.8.14
ADD ${GITHUB_BASEURL}/itzg/easy-add/releases/download/${EASY_ADD_VERSION}/easy-add_${TARGETOS}_${TARGETARCH}${TARGETVARIANT} /usr/bin/easy-add ADD ${GITHUB_BASEURL}/itzg/easy-add/releases/download/${EASY_ADD_VERSION}/easy-add_${TARGETOS}_${TARGETARCH}${TARGETVARIANT} /usr/bin/easy-add
RUN chmod +x /usr/bin/easy-add RUN chmod +x /usr/bin/easy-add
# renovate: datasource=github-releases packageName=itzg/restify ARG RESTIFY_VERSION=1.7.11
ARG RESTIFY_VERSION=1.7.16
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=${RESTIFY_VERSION} --var app=restify --file {{.app}} \ --var version=${RESTIFY_VERSION} --var app=restify --file {{.app}} \
--from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz --from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
# renovate: datasource=github-releases packageName=itzg/rcon-cli ARG RCON_CLI_VERSION=1.7.3
ARG RCON_CLI_VERSION=1.7.6
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=${RCON_CLI_VERSION} --var app=rcon-cli --file {{.app}} \ --var version=${RCON_CLI_VERSION} --var app=rcon-cli --file {{.app}} \
--from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz --from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
# renovate: datasource=github-releases packageName=itzg/mc-monitor ARG MC_MONITOR_VERSION=0.16.0
ARG MC_MONITOR_VERSION=0.16.8
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=${MC_MONITOR_VERSION} --var app=mc-monitor --file {{.app}} \ --var version=${MC_MONITOR_VERSION} --var app=mc-monitor --file {{.app}} \
--from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz --from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
# renovate: datasource=github-releases packageName=itzg/mc-server-runner ARG MC_SERVER_RUNNER_VERSION=1.14.1
ARG MC_SERVER_RUNNER_VERSION=1.15.0
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=${MC_SERVER_RUNNER_VERSION} --var app=mc-server-runner --file {{.app}} \ --var version=${MC_SERVER_RUNNER_VERSION} --var app=mc-server-runner --file {{.app}} \
--from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz --from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
# renovate: datasource=github-releases packageName=itzg/mc-image-helper versioning=loose # renovate: datasource=github-releases packageName=itzg/mc-image-helper versioning=loose
ARG MC_HELPER_VERSION=1.61.1 ARG MC_HELPER_VERSION=1.54.0
ARG MC_HELPER_BASE_URL=${GITHUB_BASEURL}/itzg/mc-image-helper/releases/download/${MC_HELPER_VERSION} ARG MC_HELPER_BASE_URL=${GITHUB_BASEURL}/itzg/mc-image-helper/releases/download/${MC_HELPER_VERSION}
# used for cache busting local copy of mc-image-helper # used for cache busting local copy of mc-image-helper
ARG MC_HELPER_REV=1 ARG MC_HELPER_REV=1
+1 -24
View File
@@ -6,7 +6,7 @@
[![](https://img.shields.io/badge/Donate-Buy%20me%20a%20coffee-orange.svg)](https://www.buymeacoffee.com/itzg) [![](https://img.shields.io/badge/Donate-Buy%20me%20a%20coffee-orange.svg)](https://www.buymeacoffee.com/itzg)
[![Documentation Status](https://readthedocs.org/projects/docker-minecraft-server/badge/?version=latest)](https://docker-minecraft-server.readthedocs.io/en/latest/?badge=latest) [![Documentation Status](https://readthedocs.org/projects/docker-minecraft-server/badge/?version=latest)](https://docker-minecraft-server.readthedocs.io/en/latest/?badge=latest)
[![Read the docs](docs/img/banner-docs.png)](https://docker-minecraft-server.readthedocs.io/) [![Read the docs](docs/img/docs-banner.png)](https://docker-minecraft-server.readthedocs.io/)
There you will find things like There you will find things like
- [Quick start with Docker Compose](https://docker-minecraft-server.readthedocs.io/en/latest/#using-docker-compose) - [Quick start with Docker Compose](https://docker-minecraft-server.readthedocs.io/en/latest/#using-docker-compose)
@@ -19,26 +19,3 @@ There you will find things like
There are also many examples located in [the examples directory](examples) of this repo. There are also many examples located in [the examples directory](examples) of this repo.
This image only supports Java edition natively; however, if looking for a server that is compatible with Bedrock edition, then use [itzg/minecraft-bedrock-server](https://github.com/itzg/docker-minecraft-bedrock-server) or [refer to this section](https://docker-minecraft-server.readthedocs.io/en/latest/misc/examples/#bedrock-compatible-server) to add Bedrock compatibility to a Java edition server. This image only supports Java edition natively; however, if looking for a server that is compatible with Bedrock edition, then use [itzg/minecraft-bedrock-server](https://github.com/itzg/docker-minecraft-bedrock-server) or [refer to this section](https://docker-minecraft-server.readthedocs.io/en/latest/misc/examples/#bedrock-compatible-server) to add Bedrock compatibility to a Java edition server.
[![Sponsors](docs/img/banner-sponsors.png)](#sponsors)
<a name="sponsors"></a>
<a href="https://spawnbox.app"><img src="https://spawnbox.app/favicon-48x48.png" alt="SpawnBox logo" width="48" align="left" /></a>
<a href="https://spawnbox.app"><b>SpawnBox</b></a> - Powered by <code>itzg/minecraft-server</code>, it's a Windows desktop app for parents, teens, and friend groups who want a Minecraft server on their own PC without learning Docker, WSL2, or networking.
<br clear="left" />
<a href="https://server.pro"><img src="https://server.pro/s/img/logo-short-192.png" alt="Server.pro logo" width="48" align="left" /></a>
<a href="https://server.pro"><b>Server.pro</b></a> - A game server hosting platform offering one-click Minecraft server deployment powered by <code>itzg/minecraft-server</code>, with global locations and an easy-to-use control panel.
<br clear="left" />
<!-- additional sponsors repeat the pattern above: floated logo + blurb + clear-left break -->
<!-- logo image preferrably hosted on an external, stable site at a size of 48x48px -->
<!-- link to sponsor site -->
<!-- one or two line summary ideally with a mention of image integration -->
[and more...](https://github.com/sponsors/itzg)
+1 -5
View File
@@ -18,7 +18,6 @@ apk add --no-cache -U \
curl \ curl \
iputils \ iputils \
git \ git \
git-lfs \
jq \ jq \
mysql-client \ mysql-client \
tzdata \ tzdata \
@@ -32,8 +31,6 @@ apk add --no-cache -U \
libpcap \ libpcap \
libwebp \ libwebp \
libcap \ libcap \
numactl \
jattach \
${EXTRA_ALPINE_PACKAGES} ${EXTRA_ALPINE_PACKAGES}
# Download and install patched knockd # Download and install patched knockd
@@ -47,5 +44,4 @@ cat <<EOF >> /etc/gitconfig
[user] [user]
name = Minecraft Server on Docker name = Minecraft Server on Docker
email = server@example.com email = server@example.com
EOF EOF
git lfs install
-2
View File
@@ -46,7 +46,6 @@ dnf install -y \
zstd \ zstd \
$([ "$os_major_version" -ge 10 ] && echo 'bzip2' || echo 'lbzip2') \ $([ "$os_major_version" -ge 10 ] && echo 'bzip2' || echo 'lbzip2') \
libpcap \ libpcap \
libcap \
libwebp \ libwebp \
findutils \ findutils \
which \ which \
@@ -82,4 +81,3 @@ cat <<EOF >> /etc/gitconfig
name = Minecraft Server on Docker name = Minecraft Server on Docker
email = server@example.com email = server@example.com
EOF EOF
git lfs install
+5 -5
View File
@@ -16,7 +16,6 @@ apt-get install -y \
iputils-ping \ iputils-ping \
curl \ curl \
git \ git \
git-lfs \
jq \ jq \
dos2unix \ dos2unix \
mysql-client \ mysql-client \
@@ -28,11 +27,13 @@ apt-get install -y \
lbzip2 \ lbzip2 \
nfs-common \ nfs-common \
libpcap0.8 \ libpcap0.8 \
libnuma1 \
libcap2-bin \
jattach \
${EXTRA_DEB_PACKAGES} ${EXTRA_DEB_PACKAGES}
# Install Git LFS
curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
apt-get update
apt-get install -y git-lfs
# Clean up APT when done # Clean up APT when done
apt-get clean apt-get clean
@@ -49,4 +50,3 @@ cat <<EOF >> /etc/gitconfig
name = Minecraft Server on Docker name = Minecraft Server on Docker
email = server@example.com email = server@example.com
EOF EOF
git lfs install
+1 -12
View File
@@ -22,15 +22,6 @@ docker run -d --pull=always \
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server -p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
``` ```
## Clean server libraries
By default, supported server types remove stale server libraries during installation by setting `CLEAN_SERVER_LIBRARIES` to `true`. Set `CLEAN_SERVER_LIBRARIES` to `false` to disable this cleanup if it causes unexpected behavior.
Currently, library cleanup is supported by
- `TYPE=PAPER`
- `TYPE=PURPUR`
## Running as alternate user/group ID ## Running as alternate user/group ID
By default, the container will switch to and run the Minecraft server as user ID 1000 and group ID 1000; however, that can be changed by setting the environment variables `UID` and `GID`. By default, the container will switch to and run the Minecraft server as user ID 1000 and group ID 1000; however, that can be changed by setting the environment variables `UID` and `GID`.
@@ -53,8 +44,6 @@ If this behavior interferes with the log content, then disable TTY or remove the
To allow time for players to finish what they're doing during a graceful server shutdown, set `STOP_SERVER_ANNOUNCE_DELAY` to a number of seconds to delay after an announcement is posted by the server. To allow time for players to finish what they're doing during a graceful server shutdown, set `STOP_SERVER_ANNOUNCE_DELAY` to a number of seconds to delay after an announcement is posted by the server.
To set a custom command to run at the start of this delay period, set `STOP_SERVER_DELAY_COMMAND` to the full command. This will run in place of the announcement.
!!! warning "Increase stop grace period" !!! warning "Increase stop grace period"
The Docker stop grace period must be increased to a value longer than the announce delay. The value to use that is longer than announce delay will vary based upon the amount of time it takes for final world data saving. If the container exits with exit code 137, then that indicates a longer grace period is needed. The Docker stop grace period must be increased to a value longer than the announce delay. The value to use that is longer than announce delay will vary based upon the amount of time it takes for final world data saving. If the container exits with exit code 137, then that indicates a longer grace period is needed.
@@ -177,7 +166,7 @@ such as:
## HTTP Proxy ## HTTP Proxy
You may configure the use of an HTTP/HTTPS proxy by passing the proxy's "host:port" via the environment variable `PROXY`. In [the example compose file](https://github.com/itzg/docker-minecraft-server/blob/master/examples/proxied/compose.yml) it references a Squid proxy. The host and port can be separately passed via the environment variables `PROXY_HOST` and `PROXY_PORT`. A `|` delimited list of hosts to exclude from proxying can be passed via `PROXY_NON_PROXY_HOSTS`. You may configure the use of an HTTP/HTTPS proxy by passing the proxy's "host:port" via the environment variable `PROXY`. In [the example compose file](https://github.com/itzg/docker-minecraft-server/blob/master/examples/docker-compose-proxied.yml) it references a Squid proxy. The host and port can be separately passed via the environment variables `PROXY_HOST` and `PROXY_PORT`. A `|` delimited list of hosts to exclude from proxying can be passed via `PROXY_NON_PROXY_HOSTS`.
## Using "noconsole" option ## Using "noconsole" option
-6
View File
@@ -78,12 +78,6 @@ To produce a multi-line MOTD, embed a newline character as `\n` in the string, s
-e MOTD="Line one\nLine two" -e MOTD="Line one\nLine two"
``` ```
From bash shell
```
-e MOTD=$'Line one\nLine two'
```
or within a compose file or within a compose file
```yaml ```yaml
Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

-9
View File
@@ -1,9 +0,0 @@
Generated at https://textcraft.net/
Line 1:
"Sponsors"
Mid
None
Minecrafter
Drop shadow
3d-style view

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

@@ -6,7 +6,7 @@ Small, none, Minecraftia
Line 2: Line 2:
"Documentation" "Documentation"
Large, none, Minecrafter Large, non, Minecrafter
Overall settings: Overall settings:
- drop shadow - drop shadow
+1 -1
View File
@@ -8,7 +8,7 @@ An option to stop the server after a specified time has been added for niche app
A `.skip-stop` file can be created in the `/data` directory to make the server skip autostopping, for as long as the file is present. The autostop timer will also be reset. A `.skip-stop` file can be created in the `/data` directory to make the server skip autostopping, for as long as the file is present. The autostop timer will also be reset.
A starting, example compose file has been provided in [examples/autostop/compose.yml](https://github.com/itzg/docker-minecraft-server/blob/master/examples/autostop/compose.yml). A starting, example compose file has been provided in [examples/docker-compose-autostop.yml](https://github.com/itzg/docker-minecraft-server/blob/master/examples/docker-compose-autostop.yml).
Enable the Autostop functionality by setting: Enable the Autostop functionality by setting:
-80
View File
@@ -1,84 +1,4 @@
## Simple image additions
You can easily build upon the base image using an inline Dockerfile.
```yaml title="compose.yaml"
services:
mc:
build:
context: .
dockerfile_inline: |
FROM itzg/minecraft-server:latest
RUN apt-get update && apt-get install -y \
webp \
&& rm -rf /var/lib/apt/lists/*
pull: true # Always pull new base image
pull_policy: build
restart: unless-stopped
environment:
EULA: true
ports:
- "25565:25565/tcp"
volumes:
- ./data:/data
```
Here is an example to add Nvidia GPU support for C2ME:
??? Example "C2ME GPU example"
```yaml title="compose.yaml"
services:
mc:
build:
context: .
dockerfile_inline: |
FROM itzg/minecraft-server:java25
# Install OpenCL loader and NVIDIA driver capabilities
RUN apt-get update && apt-get install -y \
ocl-icd-libopencl1 \
opencl-headers \
clinfo \
&& rm -rf /var/lib/apt/lists/*
# 1. Create the vendor directory
# 2. Tell OpenCL to use the NVIDIA library
RUN mkdir -p /etc/OpenCL/vendors && \
echo "libnvidia-opencl.so.1" > /etc/OpenCL/vendors/nvidia.icd
# Tell the NVIDIA container runtime to expose all GPU capabilities (including compute/utility)
ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility,graphics,video
COPY ./mods /mods
pull: true # Always pull new base image
pull_policy: build
restart: unless-stopped
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
environment:
EULA: true
TYPE: "FABRIC"
VERSION: 1.21.10
MEMORY: 8G
MODRINTH_PROJECTS: |-
fabric-api
c2me
ports:
- "25565:25565/tcp"
volumes:
- ./data:/data
```
!!! tip "For advanced use only" !!! tip "For advanced use only"
This page describes a capability that is not applicable to most users. It is only intended for rare cases when a very specific Java base image is needed or additional packages need to be installed that are not generally applicable or would bloat the image size. This page describes a capability that is not applicable to most users. It is only intended for rare cases when a very specific Java base image is needed or additional packages need to be installed that are not generally applicable or would bloat the image size.
-24
View File
@@ -21,30 +21,6 @@ docker compose -f compose-dev.yml run --rm -it [-e key=value] mc-dev
To speed up the development cycle, it is recommended to set `SETUP_ONLY` to `true` as part of the run command above. To speed up the development cycle, it is recommended to set `SETUP_ONLY` to `true` as part of the run command above.
## Building the image with a new release of a tool
In this exapmle, let's say that [mc-image-helper](https://github.com/itzg/mc-image-helper) has been [released](https://github.com/itzg/mc-image-helper/releases) at 1.56.0, but the corresponding changes in the image [scripts](https://github.com/itzg/docker-minecraft-server/tree/23205471db9814cff9c6602361dbc6cdd6c4230a/scripts) need to be tested against that version while updating [the Dockerfile](https://github.com/itzg/docker-minecraft-server/blob/23205471db9814cff9c6602361dbc6cdd6c4230a/Dockerfile#L58).
```yaml title="tests/manual/optional-projects/compose.yml" hl_lines="7"
services:
mc:
build:
# ...or wherever you cloned the docker-minecraft-server repo
context: ../../..
args:
MC_HELPER_VERSION: 1.56.0
environment:
EULA: true
TYPE: "FABRIC"
MODRINTH_PROJECTS: |
fabric-api
pl3xmap?:beta
ports:
- "25565:25565/tcp"
volumes:
- ./data:/data
```
## Using development copy of tools ## Using development copy of tools
In the cloned repo, such as [`mc-image-helper`](https://github.com/itzg/mc-image-helper), install the distribution locally by running: In the cloned repo, such as [`mc-image-helper`](https://github.com/itzg/mc-image-helper), install the distribution locally by running:
+1 -17
View File
@@ -35,20 +35,4 @@ The labels that are most interesting are:
- `org.opencontainers.image.created` : the date/time the image was built - `org.opencontainers.image.created` : the date/time the image was built
- `org.opencontainers.image.revision` : which maps to <https://github.com/itzg/docker-minecraft-server/commit/REVISION> - `org.opencontainers.image.revision` : which maps to <https://github.com/itzg/docker-minecraft-server/commit/REVISION>
- `org.opencontainers.image.version` : image tag and variant [as described in this page](../versions/java.md) - `org.opencontainers.image.version` : image tag and variant [as described in this page](../versions/java.md)
## jattach
This image bundles the [jattach](https://github.com/jattach/jattach) utility for attaching to running Java processes. It is described as
> The utility to send commands to a JVM process via Dynamic Attach mechanism.
>
> All-in-one jmap + jstack + jcmd + jinfo functionality in a single tiny program.
When exec'ed interactively into the container, jattach can be invoked against the Minecraft server's java process by using commands similar to the following
!!! example
```shell
jattach $(pgrep java) threaddump
```
+1 -68
View File
@@ -42,19 +42,6 @@ There are optional volume paths that can be attached to supply content to be cop
`/mods` `/mods`
: content in this directory is synchronized into `/data/mods` for server types that use mods, [as described above](#mods-vs-plugins). For special cases, the source can be changed by setting `COPY_MODS_SRC` and destination by setting `COPY_MODS_DEST`. : content in this directory is synchronized into `/data/mods` for server types that use mods, [as described above](#mods-vs-plugins). For special cases, the source can be changed by setting `COPY_MODS_SRC` and destination by setting `COPY_MODS_DEST`.
!!! example "Loading mods from a local directory"
This is the most basic example, where `./mods` is mounted as `/mods`. If the directory with the server's mods is located somewhere else, `./mods` can be modified accordingly.
```yaml
environment:
EULA: "TRUE"
TYPE: "NEOFORGE"
volumes:
- "./data:/data"
- "./mods:/mods"
```
`/config` `/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. The source can be changed by setting `COPY_CONFIG_SRC`. Set `SYNC_SKIP_NEWER_IN_DESTINATION=false` if you want files from `/config` to take precedence over newer files in `/data/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. The source can be changed by setting `COPY_CONFIG_SRC`. Set `SYNC_SKIP_NEWER_IN_DESTINATION=false` if you want files from `/config` to take precedence over newer files in `/data/config`.
@@ -94,13 +81,7 @@ These paths work well if you want to have a common set of modules in a separate
You can download/copy additional configuration files or other resources before the server starts by using the `APPLY_EXTRA_FILES` environment variable. This is useful for downloading configs that you want to patch or modify during the startup process. You can download/copy additional configuration files or other resources before the server starts by using the `APPLY_EXTRA_FILES` environment variable. This is useful for downloading configs that you want to patch or modify during the startup process.
The format uses a `<` separator between the destination path and the source URL/path. The format uses a `<` separator between the destination path and the source URL/path. The destination path is relative to the `/data` directory. If specifying a source path, it needs to be path mounted within the container.
The destination path is relative to the `/data` directory.
If specifying a source path, rather than URL, it needs to reference a path mounted into the container as a volume.
A source path can refer to a directory, in which case the files within that directory will be copied into the destination directory. At startup, it will take care of synchronizing the removal of files it copied when they are removed from the source.
!!! example !!! example
@@ -169,54 +150,6 @@ Disabling mods within docker compose files:
mod2.jar mod2.jar
``` ```
### Loading container configuration from a pack
A pack can ship its own container configuration so that the server type, version,
and other variables travel with the pack rather than being declared by the user.
At startup, before `TYPE` is dispatched, the container can load environment
variables from a file on disk, a URL, an entry inside an archive, or from the
`.env` of each `GENERIC_PACK(S)` entry.
- `LOAD_ENV_FROM_GENERIC_PACK`: when `true`, each entry in `GENERIC_PACKS` (after
`GENERIC_PACKS_PREFIX`/`SUFFIX` expansion) is probed for a top-level `.env`
and each one found is sourced in the same order the packs are applied (later
packs override earlier ones, matching the layering of the unpack itself). Packs
without a `.env` are skipped without error. URLs are downloaded into
`/data/packs/` and reused by the regular generic-pack unpack step, so they are
not fetched twice.
- `LOAD_ENV_FROM_FILE`: container path or URL of a shell-style env file (one
`KEY=VALUE` per line). Comments and blank lines are allowed.
- `LOAD_ENV_FROM_ARCHIVE`: container path or URL of a zip/tar archive containing
an env file. The entry is sourced into the environment.
- `LOAD_ENV_FROM_ARCHIVE_ENTRY`: relative path of the env file inside the archive.
Defaults to `.env`.
These can be combined. Load order is: generic packs first, then
`LOAD_ENV_FROM_FILE`, then `LOAD_ENV_FROM_ARCHIVE` — later loads override
earlier ones, and all of them **override** values passed via `docker run -e` (or
compose `environment:`), so the pack's declared values win.
```shell
docker run -d \
-e EULA=TRUE \
-e GENERIC_PACK=https://cdn.example.org/my-pack.zip \
-e LOAD_ENV_FROM_GENERIC_PACK=true \
itzg/minecraft-server
```
Where `my-pack.zip` contains a `.env` at its root such as:
```env
TYPE=FABRIC
VERSION=1.21.1
FABRIC_LOADER_VERSION=0.16.0
```
!!! warning
The env file is sourced by `bash`, so any shell syntax it contains will be
evaluated. Only point these variables at sources you trust. `EULA` cannot be
set this way — it is checked before the env file is loaded.
## Mods/plugins list ## Mods/plugins list
You may also download or copy over individual mods/plugins using the `MODS` or `PLUGINS` environment variables. Both are a comma or newline delimited list of You may also download or copy over individual mods/plugins using the `MODS` or `PLUGINS` environment variables. Both are a comma or newline delimited list of
+1 -48
View File
@@ -86,54 +86,6 @@ Where:
To temporarily disable processing of the `MODRINTH_PROJECTS` list, then comment out the `MODRINTH_PROJECTS` environment variable. To temporarily disable processing of the `MODRINTH_PROJECTS` list, then comment out the `MODRINTH_PROJECTS` environment variable.
## Optional projects
Projects that are not critical for the server to function can be marked as **optional** by appending a `?` to the project slug or ID. When a compatible version cannot be found for an optional project, the server logs a warning and continues startup instead of failing.
This is particularly useful for server-side mods that tend to lag behind on Minecraft updates, such as map renderers (Pl3xmap, BlueMap), performance mods (Lithium, C2ME), or admin tools (Spark, LuckPerms).
```yaml
MODRINTH_PROJECTS: |
fabric-api
lithium
pl3xmap?
bluemap?:beta
```
The `?` marker can be combined with all existing format options:
| Format | Example |
|----------------------------|---------------------------|
| Slug only | `pl3xmap?` |
| With version | `pl3xmap?:Oa9ZDzZq` |
| With release type | `pl3xmap?:beta` |
| With loader prefix | `fabric:pl3xmap?` |
| Full combination | `fabric:pl3xmap?:beta` |
| In listing files | `pl3xmap?` *(one per line)* |
When combined with [`VERSION_FROM_MODRINTH_PROJECTS`](#version-from-projects), optional projects are **excluded** from the version calculation. This means an optional mod that hasn't been updated yet will never block a Minecraft version upgrade.
!!! example "Automatic upgrades without optional-mod breakage"
```yaml
MODRINTH_PROJECTS: |
fabric-api
lithium
pl3xmap?
VERSION_FROM_MODRINTH_PROJECTS: true
```
If a new Minecraft version is released and `fabric-api` + `lithium` support it but `pl3xmap` does not:
1. The resolved `VERSION` is set to the new version (pl3xmap is not considered)
2. `fabric-api` and `lithium` are installed normally
3. `pl3xmap` is skipped with a warning in the logs
4. On a future restart, once pl3xmap publishes a compatible build, it is picked up automatically
!!! note
Optional projects marked with `?` in listing files (`@/path/to/file.txt`) are supported ; the `?` is parsed from each line the same way as inline entries.
## Version from Projects ## Version from Projects
When the environment variable `VERSION_FROM_MODRINTH_PROJECTS` is set to "true" the Minecraft [`VERSION`](../versions/minecraft.md) will be automatically determined by looking at the most recent version of Minecraft that is supported by all the projects provided in `MODRINTH_PROJECTS`. When the environment variable `VERSION_FROM_MODRINTH_PROJECTS` is set to "true" the Minecraft [`VERSION`](../versions/minecraft.md) will be automatically determined by looking at the most recent version of Minecraft that is supported by all the projects provided in `MODRINTH_PROJECTS`.
@@ -163,3 +115,4 @@ When the environment variable `VERSION_FROM_MODRINTH_PROJECTS` is set to "true"
`MODRINTH_LOADER` `MODRINTH_LOADER`
: When using a custom server, set this to specify which loader type will be requested during lookups : When using a custom server, set this to specify which loader type will be requested during lookups
-2
View File
@@ -13,8 +13,6 @@ docker run -d --pull=always \
packwiz modpack definitions 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 modpack definitions 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).
If the pack ships a `.env` file that you reference with `LOAD_ENV_FROM_FILE`, that file is re-loaded immediately after the packwiz installer runs, so the freshly downloaded values are applied to the remaining startup stages. Note that `TYPE` and `VERSION` are resolved earlier (before the deploy is dispatched), so a pack-provided `.env` cannot change those from within packwiz; use `LOAD_ENV_FROM_GENERIC_PACK` or `LOAD_ENV_FROM_ARCHIVE` for those.
!!! note !!! note
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. 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.
+12 -12
View File
@@ -1,25 +1,25 @@
click==8.4.2 click==8.3.1
colorama==0.4.6 colorama==0.4.6
deepmerge==2.1.0 deepmerge==2.0
ghp-import==2.1.0 ghp-import==2.1.0
griffe==2.1.0 griffe==2.0.0
Jinja2==3.1.6 Jinja2==3.1.6
Markdown==3.10.2 Markdown==3.10.2
MarkupSafe==3.0.3 MarkupSafe==3.0.3
mergedeep==1.3.4 mergedeep==1.3.4
mkdocs==1.6.1 mkdocs==1.6.1
mkdocs-autorefs==1.4.4 mkdocs-autorefs==1.4.4
mkdocs-get-deps==0.2.2 mkdocs-get-deps==0.2.0
mkdocstrings==1.0.4 mkdocstrings==1.0.3
mkdocstrings-python==2.0.5 mkdocstrings-python==2.0.2
packaging==26.2 packaging==26.0
pathspec==1.1.1 pathspec==1.0.4
platformdirs==4.10.0 platformdirs==4.9.2
Pygments==2.20.0 Pygments==2.19.2
pymdown-extensions==11.0 pymdown-extensions==10.21
python-dateutil==2.9.0.post0 python-dateutil==2.9.0.post0
PyYAML==6.0.3 PyYAML==6.0.3
pyyaml_env_tag==1.1 pyyaml_env_tag==1.1
six==1.17.0 six==1.17.0
watchdog==6.0.0 watchdog==6.0.0
zensical==0.0.46 # zensical @ file:///
+2 -2
View File
@@ -6,7 +6,7 @@ The container can host an SSH console. It is enabled by setting `ENABLE_SSH` to
The SSH server only supports password based authentication. The password is the same as the RCON password. The SSH server only supports password based authentication. The password is the same as the RCON password.
!!! question !!! question
See [the RCON password](../configuration/server-properties.md#rcon-password) section under configuration/server-properties for more information on how to set an RCON password. See [the RCON password](../configuration/server-properties.md/#rcon-password) section under configuration/server-properties for more information on how to set an RCON password.
The SSH server runs on port `2222` inside the container. The SSH server runs on port `2222` inside the container.
@@ -15,7 +15,7 @@ The SSH server runs on port `2222` inside the container.
!!! warning "Security Implications" !!! warning "Security Implications"
By default, publishing ports in Docker binds them to all network interfaces (`0.0.0.0`), making the SSH console accessible to any device that can reach your host machine. By default, publishing ports in Docker binds them to all network interfaces (`0.0.0.0`), making the SSH console accessible to any device that can reach your host machine.
Since the SSH console grants **full administrative access** to your server, it is critical to use a strong [RCON password](../configuration/server-properties.md#rcon-password). Since the SSH console grants **full administrative access** to your server, it is critical to use a strong [RCON password](../configuration/server-properties.md/#rcon-password).
If you wish to restrict access to the local machine only, refer to the [Docker documentation](https://docs.docker.com/engine/network/port-publishing/#publishing-ports) on binding to specific IP addresses (e.g., `127.0.0.1:2222:2222`). If you wish to restrict access to the local machine only, refer to the [Docker documentation](https://docs.docker.com/engine/network/port-publishing/#publishing-ports) on binding to specific IP addresses (e.g., `127.0.0.1:2222:2222`).
+2 -2
View File
@@ -26,9 +26,9 @@ When a connection is established, the last 50 (by default, configurable with `WE
!!! warning "Security Implications" !!! warning "Security Implications"
By default, publishing ports in Docker binds them to all network interfaces (`0.0.0.0`), making the WebSocket console accessible to any device that can reach your host machine. By default, publishing ports in Docker binds them to all network interfaces (`0.0.0.0`), making the WebSocket console accessible to any device that can reach your host machine.
Since the WebSocket console grants **full administrative access** to your server, it is critical to use a strong [WebSocket password](#password) or [RCON password](../configuration/server-properties.md#rcon-password). Since the WebSocket console grants **full administrative access** to your server, it is critical to use a strong [WebSocket password](#password) or [RCON password](../configuration/server-properties.md/#rcon-password).
If you wish to restrict access to the local machine only, refer to the [Docker documentation](https://docs.docker.com/engine/network/port-publishing#publishing-ports) on binding to specific IP addresses (e.g., `127.0.0.1:80:80`). If you wish to restrict access to the local machine only, refer to the [Docker documentation](https://docs.docker.com/engine/network/port-publishing/#publishing-ports) on binding to specific IP addresses (e.g., `127.0.0.1:80:80`).
If WebSocket access is only intended for inter-container connections, consider **NOT** forwarding the port to the host machine, and putting the containers in a shared [Docker network](https://docs.docker.com/engine/network/#user-defined-networks). If WebSocket access is only intended for inter-container connections, consider **NOT** forwarding the port to the host machine, and putting the containers in a shared [Docker network](https://docs.docker.com/engine/network/#user-defined-networks).
@@ -35,7 +35,7 @@ For optimal performance choose java25 with GTNH 2.8.0 and later.
## Config backups ## Config backups
During version upgrade, the server will replace all config files to make sure all new features are setup as intended. The old config files are stored in a backup folder in the data directory, for you to use as reference for manual reapplication of your changed settings. The folder name starts with `gtnh-upgrade-` followed by a timestamp. Set the environment variable `GTNH_DELETE_BACKUPS` to true to delete all backup folders at startup. During version upgrade, the server will replace all config files to make sure all new features are setup as intended. The old config files are stored in a backup folder in the data directory, for you to use as reference for manual reapplication of your changed settings. Set the environment variable `GTNH_DELETE_BACKUPS` to true to delete all backup folders at startup.
## server.properties defaults ## server.properties defaults
@@ -18,7 +18,7 @@ The desired modpack project is specified with the `MODRINTH_MODPACK` environment
- A custom URL of a hosted [mrpack file](https://support.modrinth.com/en/articles/8802351-modrinth-modpack-format-mrpack) - A custom URL of a hosted [mrpack file](https://support.modrinth.com/en/articles/8802351-modrinth-modpack-format-mrpack)
- The container path to a local [mrpack file](https://support.modrinth.com/en/articles/8802351-modrinth-modpack-format-mrpack). The file name **must have the `.mrpack` extension** in order to be correctly detected as a local file. - The container path to a local [mrpack file](https://support.modrinth.com/en/articles/8802351-modrinth-modpack-format-mrpack)
## Modpack version ## Modpack version
+1 -13
View File
@@ -246,12 +246,6 @@ alternatively, you can mount: <code>/etc/localtime:/etc/localtime:ro
<td><code></code></td> <td><code></code></td>
<td>⬜️</td> <td>⬜️</td>
</tr> </tr>
<tr>
<td><code>STOP_SERVER_DELAY_COMMAND</code></td>
<td>To set a custom command to run at the start of this delay period, set <code>STOP_SERVER_DELAY_COMMAND</code> to the full command. This will run in place of the announcement.</td>
<td><code></code></td>
<td>⬜️</td>
</tr>
<tr> <tr>
<td><code>PROXY</code></td> <td><code>PROXY</code></td>
<td>You may configure the use of an HTTP/HTTPS proxy by passing the proxy's URL</td> <td>You may configure the use of an HTTP/HTTPS proxy by passing the proxy's URL</td>
@@ -403,12 +397,6 @@ This image maps known server properties as described in [this section](configura
<td><code>Randomly generated</code></td> <td><code>Randomly generated</code></td>
<td>✅</td> <td>✅</td>
</tr> </tr>
<tr>
<td><code>RCON_PASSWORD_FILE</code></td>
<td>Can be set to read the RCON password from a file. Overrides <code>RCON_PASSWORD</code> if both are set.</td>
<td><code></code></td>
<td>⬜️</td>
</tr>
<tr> <tr>
<td><code>RCON_PORT</code></td> <td><code>RCON_PORT</code></td>
<td>The port for RCON</td> <td>The port for RCON</td>
@@ -676,4 +664,4 @@ This image maps known server properties as described in [this section](configura
<td></td> <td></td>
<td><code></code></td> <td><code></code></td>
<td>⬜️</td> <td>⬜️</td>
</tr> --> </tr> -->
+9 -4
View File
@@ -15,19 +15,25 @@ where `<tag>` refers to the first column of this table:
| latest | 25 | Ubuntu | Hotspot | amd64, arm64 | | | latest | 25 | Ubuntu | Hotspot | amd64, arm64 | |
| stable | 25 | Ubuntu | Hotspot | amd64, arm64 | | | stable | 25 | Ubuntu | Hotspot | amd64, arm64 | |
| java25 | 25 | Ubuntu | Hotspot | amd64, arm64 | | | java25 | 25 | Ubuntu | Hotspot | amd64, arm64 | |
| java25-alpine | 25 | Alpine | Hotspot | amd64, arm64 | |
| java25-jdk | 25 | Ubuntu | Hotspot+JDK | amd64, arm64 | | | java25-jdk | 25 | Ubuntu | Hotspot+JDK | amd64, arm64 | |
| java25-graalvm | 25 | Oracle | Oracle GraalVM (3) | amd64, arm64 | (5) |
| java21 | 21 | Ubuntu | Hotspot | amd64, arm64 | | | java21 | 21 | Ubuntu | Hotspot | amd64, arm64 | |
| java21-jdk | 21 | Ubuntu | Hotspot+JDK | amd64, arm64 | | | java21-jdk | 21 | Ubuntu | Hotspot+JDK | amd64, arm64 | |
| java21-alpine | 21 | Alpine | Hotspot | amd64, arm64 | | | java21-alpine | 21 | Alpine | Hotspot | amd64, arm64 | |
| java21-graalvm | 21 | Oracle | Oracle GraalVM (3) | amd64, arm64 | (5) |
| java17 | 17 | Ubuntu | Hotspot | amd64, arm64, armv7 | | | java17 | 17 | Ubuntu | Hotspot | amd64, arm64, armv7 | |
| java16 | 16 | Ubuntu | Hotspot | amd64, arm64, armv7 | (1) | | java17-graalvm | 17 | Oracle | Oracle GraalVM (3) | amd64, arm64 | (5) |
| java16 | 16 | Ubuntu | Hotspot | amd64, arm64, armv7 | (4) |
| java11 | 11 | Ubuntu | Hotspot | amd64, arm64, armv7 | | | java11 | 11 | Ubuntu | Hotspot | amd64, arm64, armv7 | |
| java8 | 8 | Ubuntu | Hotspot | amd64, arm64, armv7 | | | java8 | 8 | Ubuntu | Hotspot | amd64, arm64, armv7 | |
Notes Notes
1. This version of Java is [recommended for PaperMC 1.16.5](https://docs.papermc.io/paper/getting-started/#requirements) 1. Why no arm64 for Java 17 Alpine? That is because the base images, such as [elipse-temurin](https://hub.docker.com/_/eclipse-temurin/tags?page=&page_size=&ordering=&name=17-jre-alpine) do not provide support for that. Use the Ubuntu-based images instead.
2. Short-term variant, subject to deprecation upon next version introduction
3. Based on the [Oracle GraalVM images](https://blogs.oracle.com/java/post/new-oracle-graalvm-container-images), which as of JDK 17, are now under the [GraalVM Free License](https://blogs.oracle.com/java/post/graalvm-free-license) incorporating what used to be known as the GraalVM Enterprise.
4. This version of Java is [recommended for PaperMC 1.16.5](https://docs.papermc.io/paper/getting-started/#requirements)
5. Due to these images using Oracle Linux, (which is based on Red Hat Enterprise Linux) Forge Installer will not work due to its use of zlib-ng. Use other images for initial installation and Forge version upgrade.
!!! example "Example using java8" !!! example "Example using java8"
@@ -121,7 +127,6 @@ Forge also doesn't support openj9 JVM implementation.
The following image tags have been deprecated and are no longer receiving updates: The following image tags have been deprecated and are no longer receiving updates:
- java25-graalvm, java21-graalvm, java17-graalvm
- adopt13 - adopt13
- adopt14 - adopt14
- adopt15 - adopt15
+1 -2
View File
@@ -2,8 +2,7 @@ To use a different Minecraft version, pass the `VERSION` environment variable (c
- `LATEST` for latest release (the default) - `LATEST` for latest release (the default)
- `SNAPSHOT` for latest snapshot - `SNAPSHOT` for latest snapshot
- a specific legacy version, such as `1.7.9`, `25w35a`, `1.15.2-pre2` or `1.21.11-rc1` - a specific version, such as `1.7.9`, `25w35a`, `26.1`, or `26.1-snapshot-1`
- a specific [new version numbering system](https://www.minecraft.net/en-us/article/minecraft-new-version-numbering-system) version like `26.1`, `26.1-snapshot-1`, `26.1-pre-1`, or `26.1-rc-1`
- or an alpha and beta version, such as "b1.7.3" (server download might not exist) - or an alpha and beta version, such as "b1.7.3" (server download might not exist)
For example, to use the latest snapshot: For example, to use the latest snapshot:
-45
View File
@@ -1,45 +0,0 @@
# Podman Quadlet Example
This example demonstrates how to deploy multiple autoscaling minecraft servers behind mc-router with [podman quadlets](https://docs.podman.io/en/stable/markdown/podman-systemd.unit.5.html).
The commands listed below assume rootless podman but can easily be modified for rootful.
## mc-router.host label
In `mc@.container`, replace `example.com` with your domain.
## Server instance configuration
Each server instance requries an environment file with a matching name in the mc folder; e.g. instance `example` uses `mc/example.env`.[^1]
## Container auto-removal fix
Once the quadlets files are installed and daemon-reloaded, the generated service file needs to be edited due to generated quadlets always adding `--rm`.[^2]
To fix this, run `systemctl --user edit mc@.service` and replace the `ExecStart` entry with a copy that substitues `--restart=unless-stopped` where `--rm` is.
The drop-in should look something like this:
```ini
[Service]
ExecStart=
ExecStart=/usr/bin/podman run --name %p-%i --replace --restart=unless-stopped ...
```
## Start containers/services
```sh
systemctl --user enable --now podman.socket
systemctl --user start mc@example.service mc-router.service
# instances are enabled by symlinking from the template
ln -s ${XDG_CONFIG_HOME}/containers/systemd/mc@.service ${XDG_CONFIG_HOME}/containers/systemd/mc@example.service
```
## Rootless notes
If running rootless, be sure to enable lingering with `sudo loginctl enable-linger $USER`.
Also note that source IPs are currently lost due to how rootless podman handles custom networks.
This should be fixed in a future podman release.[^3]
[^1]: The base config is a [template file](https://docs.podman.io/en/stable/markdown/podman-systemd.unit.5.html#template-files) with instance names after the @ sign .
[^2]: <https://github.com/podman-container-tools/podman/discussions/28837>
[^3]: <https://github.com/podman-container-tools/podman/pull/28478>
@@ -1,24 +0,0 @@
[Unit]
Description=Minecraft proxy with autoscaling support
[Container]
Image=docker.io/itzg/mc-router
ContainerName=%N
AutoUpdate=registry
UserNS=host
Volume=%t/podman/podman.sock:/var/run/docker.sock:ro
Network=minecraft.network
PublishPort=25565:25565
SecurityLabelDisable=true
Environment=\
"IN_DOCKER=true" \
"AUTO_SCALE_DOWN=true" \
"AUTO_SCALE_UP=true" \
"AUTO_SCALE_DOWN_AFTER=10m" \
"AUTO_SCALE_ASLEEP_MOTD='Server is asleep. Join again to wake it up!'"
[Service]
Restart=always
[Install]
WantedBy=default.target
-9
View File
@@ -1,9 +0,0 @@
# General options
INIT_MEMORY=1G
MAX_MEMORY=4G
# Server options
EULA=TRUE
VIEW_DISTANCE=16
DIFFICULTY=normal
MOTD=Example Server!\nRunning version %VERSION%
-26
View File
@@ -1,26 +0,0 @@
[Unit]
Description=Minecraft server instance
Before=mc-router.service
[Container]
Image=docker.io/itzg/minecraft-server
ContainerName=%p-%i
AutoUpdate=registry
UserNS=auto
Volume=%p-%i:/data:Z,U
Network=minecraft.network
PodmanArgs=--tty --interactive
HealthCmd="/usr/local/bin/mc-health"
HealthInterval=10s
HealthRetries=20
HealthStartPeriod=1m
HealthTimeout=10s
Label=mc-router.host=%p-%i.example.com
EnvironmentFile=./mc/%i.env
[Service]
Restart=on-abnormal
RemainAfterExit=yes
[Install]
WantedBy=default.target
@@ -1,2 +0,0 @@
[Network]
Driver=bridge
+3 -1
View File
@@ -10,6 +10,7 @@ services:
VANILLATWEAKS_FILE: /config/vanillatweaks-datapacks.json VANILLATWEAKS_FILE: /config/vanillatweaks-datapacks.json
REMOVE_OLD_VANILLATWEAKS: "TRUE" REMOVE_OLD_VANILLATWEAKS: "TRUE"
volumes: volumes:
- data:/data
- ./vanillatweaks-datapacks.json:/config/vanillatweaks-datapacks.json:ro - ./vanillatweaks-datapacks.json:/config/vanillatweaks-datapacks.json:ro
vanillatweaks_sharecode: vanillatweaks_sharecode:
# port is set to 25566 to not conflict with vanillatweaks_file example # port is set to 25566 to not conflict with vanillatweaks_file example
@@ -34,6 +35,7 @@ services:
VANILLATWEAKS_FILE: /config/vanillatweaks-datapacks.json,/config/vanillatweaks-resourcepacks.json,/config/vanillatweaks-craftingtweaks.json VANILLATWEAKS_FILE: /config/vanillatweaks-datapacks.json,/config/vanillatweaks-resourcepacks.json,/config/vanillatweaks-craftingtweaks.json
REMOVE_OLD_VANILLATWEAKS: "TRUE" REMOVE_OLD_VANILLATWEAKS: "TRUE"
volumes: volumes:
- data:/data
- ./vanillatweaks-datapacks.json:/config/vanillatweaks-datapacks.json:ro - ./vanillatweaks-datapacks.json:/config/vanillatweaks-datapacks.json:ro
- ./vanillatweaks-resourcepacks.json:/config/vanillatweaks-resourcepacks.json:ro - ./vanillatweaks-resourcepacks.json:/config/vanillatweaks-resourcepacks.json:ro
- ./vanillatweaks-craftingtweaks.json:/config/vanillatweaks-craftingtweaks.json:ro - ./vanillatweaks-craftingtweaks.json:/config/vanillatweaks-craftingtweaks.json:ro
-7
View File
@@ -82,7 +82,6 @@
"iceberg", "iceberg",
"ignitioncoil", "ignitioncoil",
"illager-raid-music", "illager-raid-music",
"immersive-damage-indicators",
"inmisaddon", "inmisaddon",
"iris-flywheel-compat", "iris-flywheel-compat",
"irisshaders", "irisshaders",
@@ -145,7 +144,6 @@
"smart-hud", "smart-hud",
"smithing-template-viewer", "smithing-template-viewer",
"smooth-font", "smooth-font",
"smooth-swapping",
"smoothwater", "smoothwater",
"sodium", "sodium",
"sodium-extra", "sodium-extra",
@@ -213,11 +211,6 @@
}, },
"valhelsia-5": { "valhelsia-5": {
"excludes": ["modernfix"] "excludes": ["modernfix"]
},
"wolds-vaults": {
"forceIncludes": [
"just-enough-resources-jer"
]
} }
} }
} }
+4 -2
View File
@@ -5,6 +5,7 @@
"AmbientSounds", "AmbientSounds",
"amecs", "amecs",
"Animation_Overhaul", "Animation_Overhaul",
"appleskin",
"auudio", "auudio",
"axolotlbuckets", "axolotlbuckets",
"BadOptimizations", "BadOptimizations",
@@ -27,6 +28,7 @@
"compass-coords", "compass-coords",
"colorwheel", "colorwheel",
"connectedness", "connectedness",
"connector",
"continuity", "continuity",
"controlling", "controlling",
"craftpresence", "craftpresence",
@@ -37,6 +39,8 @@
"distraction_free_recipes", "distraction_free_recipes",
"drippyloadingscreen", "drippyloadingscreen",
"eating-animation", "eating-animation",
"emi",
"emi_loot",
"emi_trade", "emi_trade",
"emiffect", "emiffect",
"emitrades", "emitrades",
@@ -56,7 +60,6 @@
"gpumemleakfix", "gpumemleakfix",
"Highlighter", "Highlighter",
"ImmediatelyFast", "ImmediatelyFast",
"immersivedamageindicators",
"indium", "indium",
"inventory-profiles-next", "inventory-profiles-next",
"iris", "iris",
@@ -91,7 +94,6 @@
"seasonhud", "seasonhud",
"ShoulderSurfing", "ShoulderSurfing",
"skinlayers3d", "skinlayers3d",
"smoothswapping",
"sodium", "sodium",
"sorted_enchantments", "sorted_enchantments",
"tooltipfix", "tooltipfix",
+1 -1
View File
@@ -41,7 +41,7 @@
"max-players": {"env": "MAX_PLAYERS"}, "max-players": {"env": "MAX_PLAYERS"},
"max-tick-time": {"env": "MAX_TICK_TIME"}, "max-tick-time": {"env": "MAX_TICK_TIME"},
"max-world-size": {"env": "MAX_WORLD_SIZE"}, "max-world-size": {"env": "MAX_WORLD_SIZE"},
"motd": {"env": "MOTD", "translateLiteralNewlines": true}, "motd": {"env": "MOTD"},
"network-compression-threshold": {"env": "NETWORK_COMPRESSION_THRESHOLD"}, "network-compression-threshold": {"env": "NETWORK_COMPRESSION_THRESHOLD"},
"online-mode": {"env": "ONLINE_MODE"}, "online-mode": {"env": "ONLINE_MODE"},
"op-permission-level": {"env": "OP_PERMISSION_LEVEL"}, "op-permission-level": {"env": "OP_PERMISSION_LEVEL"},
+4 -14
View File
@@ -2,7 +2,7 @@
{ {
"tag": "latest", "tag": "latest",
"notes": "Always tracks the most recent commit on the main branch", "notes": "Always tracks the most recent commit on the main branch",
"java": "25", "java": "21",
"distribution": "ubuntu", "distribution": "ubuntu",
"jvm": "hotspot", "jvm": "hotspot",
"architectures": ["amd64", "arm64"], "architectures": ["amd64", "arm64"],
@@ -24,20 +24,12 @@
"jvm": "hotspot", "jvm": "hotspot",
"architectures": ["amd64", "arm64"] "architectures": ["amd64", "arm64"]
}, },
{
"tag": "java25-alpine",
"java": "25",
"distribution": "alpine",
"jvm": "hotspot",
"architectures": ["amd64", "arm64"]
},
{ {
"tag": "java25-graalvm", "tag": "java25-graalvm",
"java": "25", "java": "25",
"distribution": "oracle", "distribution": "oracle",
"jvm": "graalvm", "jvm": "graalvm",
"architectures": ["amd64", "arm64"], "architectures": ["amd64", "arm64"]
"deprecated": true
}, },
{ {
"tag": "java24", "tag": "java24",
@@ -75,8 +67,7 @@
"java": "21", "java": "21",
"distribution": "oracle", "distribution": "oracle",
"jvm": "graalvm", "jvm": "graalvm",
"architectures": ["amd64", "arm64"], "architectures": ["amd64", "arm64"]
"deprecated": true
}, },
{ {
"tag": "java21-jdk", "tag": "java21-jdk",
@@ -150,5 +141,4 @@
{"tag": "java8-jdk", "deprecated": true}, {"tag": "java8-jdk", "deprecated": true},
{"tag": "java8-openj9", "deprecated": true}, {"tag": "java8-openj9", "deprecated": true},
{"tag": "java8-graalvm-ce", "deprecated": true} {"tag": "java8-graalvm-ce", "deprecated": true}
]
]
Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 83 KiB

+1 -2
View File
@@ -11,6 +11,5 @@
"# renovate: datasource=(?<datasource>[a-z-]+?)(?: packageName=(?<packageName>.+?))?(?: versioning=(?<versioning>[a-z-]+))?\\s(?:ENV|ARG) .+?_VERSION=(?<currentValue>.+?)\\s" "# renovate: datasource=(?<datasource>[a-z-]+?)(?: packageName=(?<packageName>.+?))?(?: versioning=(?<versioning>[a-z-]+))?\\s(?:ENV|ARG) .+?_VERSION=(?<currentValue>.+?)\\s"
] ]
} }
], ]
"labels": ["dependencies"]
} }
+4 -34
View File
@@ -54,8 +54,8 @@ fi
if isTrue "${DEBUG_MEMORY:-false}"; then if isTrue "${DEBUG_MEMORY:-false}"; then
log "Memory usage and availability (in MB)" log "Memory usage and availability (in MB)"
uname -pars | applyLogPrefix uname -pars
free -m | applyLogPrefix free -m
fi fi
########################################## ##########################################
@@ -123,8 +123,7 @@ function addToProxyArgs() {
addToProxyArgs http.proxyHost "${PROXY_HOST:-}" addToProxyArgs http.proxyHost "${PROXY_HOST:-}"
addToProxyArgs http.proxyPort "${PROXY_PORT:-}" addToProxyArgs http.proxyPort "${PROXY_PORT:-}"
addToProxyArgs http.nonProxyHosts "${PROXY_NON_PROXY_HOSTS:-}" addToProxyArgs http.nonProxyHosts "${PROXY_NON_PROXY_HOSTS:-}"
LOCAL_IFS=$IFS; IFS=' '; MC_IMAGE_HELPER_OPTS+=" ${proxyArgs[*]}"; IFS=$LOCAL_IFS export MC_IMAGE_HELPER_OPTS+=" ${proxyArgs[*]}"
export MC_IMAGE_HELPER_OPTS
function fixJavaPath() { function fixJavaPath() {
# Some Docker management UIs grab all the image declared variables and present them for configuration. # Some Docker management UIs grab all the image declared variables and present them for configuration.
@@ -153,40 +152,11 @@ fi
cd /data || exit 1 cd /data || exit 1
##########################################
# Optionally load environment variables from a file or archive entry,
# allowing packs/artifacts to declare TYPE, VERSION and other settings
# inside-out. Loaded values override anything passed in through docker -e.
# Generic packs are processed first so that LOAD_ENV_FROM_FILE and
# LOAD_ENV_FROM_ARCHIVE can override any values they set.
if isTrue "${LOAD_ENV_FROM_GENERIC_PACK:-false}"; then
if ! loadEnvFromGenericPack; then
exit 1
fi
fi
if [[ ${LOAD_ENV_FROM_FILE:-} ]]; then
if ! loadEnvFromFile "${LOAD_ENV_FROM_FILE}"; then
exit 1
fi
fi
if [[ ${LOAD_ENV_FROM_ARCHIVE:-} ]]; then
if ! loadEnvFromArchive "${LOAD_ENV_FROM_ARCHIVE}" "${LOAD_ENV_FROM_ARCHIVE_ENTRY:-.env}"; then
exit 1
fi
fi
export DECLARED_TYPE=${TYPE^^} export DECLARED_TYPE=${TYPE^^}
export DECLARED_VERSION="$VERSION" export DECLARED_VERSION="$VERSION"
if isTrue "${VERSION_FROM_MODRINTH_PROJECTS:-}" && [[ ${MODRINTH_PROJECTS:-} ]]; then if isTrue "${VERSION_FROM_MODRINTH_PROJECTS:-}" && [[ ${MODRINTH_PROJECTS:-} ]]; then
args=() if ! VERSION=$(mc-image-helper version-from-modrinth-projects --projects "${MODRINTH_PROJECTS}"); then
if [[ ${MODRINTH_PROJECTS_DEFAULT_VERSION_TYPE:-} ]]; then
args+=(--allowed-version-type "${MODRINTH_PROJECTS_DEFAULT_VERSION_TYPE:-}")
fi
if ! VERSION=$(mc-image-helper version-from-modrinth-projects "${args[@]}" --projects "${MODRINTH_PROJECTS}"); then
logError "failed to resolve version from MODRINTH_PROJECTS: ${MODRINTH_PROJECTS}" logError "failed to resolve version from MODRINTH_PROJECTS: ${MODRINTH_PROJECTS}"
exit 1 exit 1
fi fi
+161 -165
View File
@@ -6,71 +6,84 @@
# Define setup functions # Define setup functions
function getGTNHdownloadPath(){ function getGTNHdownloadPath(){
gtnh_download_path="" gtnh_download_path=""
local release_object=""
local current_java_version=""
current_java_version=$(mc-image-helper java-release) current_java_version=$(mc-image-helper java-release)
# Select release JSON object if ! packs_data="$(restify --tag=a https://www.gtnewhorizons.com/version-history/ | jq -r '.[].href | select(test("Server"))')"; then
if [ "$GTNH_PACK_VERSION" == "latest-dev" ]; then logError "Failed to retrieve data from http://downloads.gtnewhorizons.com/ServerPacks/?raw"
if ! release_object="$(
curl -fsSL "https://downloads.gtnewhorizons.com/versions.json" \
| jq -r '(.versions // .)|to_entries|sort_by(.value.releaseDate)|map(select(.value.title=="Beta release"))|.[-1]'
)"; then logError "Failed to retrieve release from https://downloads.gtnewhorizons.com/versions.json"
exit 1
fi
log "Selected $(jq '.key' <<< "$release_object") as latest dev version for download."
elif [ "$GTNH_PACK_VERSION" == "latest" ]; then
if ! release_object="$(
curl -fsSL "https://downloads.gtnewhorizons.com/versions.json" \
| jq -r '(.versions // .)|to_entries|sort_by(.value.releaseDate)|map(select(.value.title=="Stable release"))|.[-1]'
)"; then logError "Failed to retrieve release from https://downloads.gtnewhorizons.com/versions.json"
exit 1
fi
log "Selected $(jq '.key' <<< "$release_object") as latest version for download."
else
if ! release_object="$(
curl -fsSL "https://downloads.gtnewhorizons.com/versions.json" \
| jq -r --arg USRIN "$GTNH_PACK_VERSION" '(.versions // .)|to_entries|sort_by(.value.releaseDate)|map(select(.key==$USRIN))|.[]'
)"; then logError "Failed to retrieve release from https://downloads.gtnewhorizons.com/versions.json"
exit 1
fi
log "Selected $(jq -r '.key' <<< "$release_object") as matching version for download."
fi
if [[ -z $release_object ]]; then
logError "No release found for GTNH_PACK_VERSION=$GTNH_PACK_VERSION. Please check if the version is valid."
exit 1 exit 1
fi fi
mapfile -t packs <<< "$packs_data"
# Select compatible server files for java version
if (( current_java_version == 8 )); then log "Start locating server files..."
gtnh_download_path=$(jq -r '.value.server.java8Url' <<< "$release_object") for pack in "${packs[@]}"; do
log "Use GTNH Server Java 8 release." # Extract the Java version(s) from the pack filename
if ! pack_java_version=$(basename "$pack" | grep -Eo 'Java_[0-9]+(-[0-9]+)?' | sed 's/Java_//'); then
elif (( current_java_version >= 17 )); then logWarning "Could not parse java version of $pack"
if (( current_java_version > $(jq '.value.maxJavaVersion' <<< "$release_object") )); then
logError "Container Java version $current_java_version is not supported by GTNH. Try an older release."
exit 1
fi fi
gtnh_download_path=$(jq -r '.value.server.java17_2XUrl' <<< "$release_object") # Skip the pack if the current Java version is not compatible
log "Use GTNH Server Java 17+ release." if [[ "$pack_java_version" == *-* ]]; then
# Handle range of Java versions (e.g., "17-21")
java_min_version=$(echo "$pack_java_version" | cut -d'-' -f1)
java_max_version=$(echo "$pack_java_version" | cut -d'-' -f2)
if (( current_java_version < java_min_version || current_java_version > java_max_version )); then
debug "Skipping $pack due to incompatible Java version: $current_java_version not in range $java_min_version-$java_max_version"
continue
fi
else
# Handle single Java version (e.g., "8")
if (( current_java_version != pack_java_version )); then
debug "Skipping $pack due to incompatible Java version: $current_java_version != $pack_java_version"
continue
fi
fi
else # Extract version numbers and release type (beta or RC) from the file names
logError "Container Java version $current_java_version is not supported by GTNH."
exit 1 if ! pack_version=$(basename "$pack" | grep -Eo '[0-9]+(\.[0-9]+)+'); then
logWarning "Could not parse version of $pack"
fi fi
if ! pack_release_type=$(basename "$pack" | grep -Eo '(beta|RC)(-[0-9]+)?' || echo ""); then
if [[ -z $gtnh_download_path ]]; then logWarning "Could not parse release type of $pack"
logError "Server files not found! Please check if the selected GTNH_PACK_VERSION=$GTNH_PACK_VERSION is valid." fi
exit 1 if ! current_version=$(basename "$gtnh_download_path" | grep -Eo '[0-9]+(\.[0-9]+)+'); then
fi debug "Could not parse version of selected download path. String might be empty."
debug "Download source URL: $gtnh_download_path" fi
if ! current_release_type=$(basename "$gtnh_download_path" | grep -Eo '(beta|RC)(-[0-9]+)?' || echo ""); then
debug "Could not parse release type of selected download path. String might be empty."
fi
# Check if the pack matches the desired type based on GTNH_PACK_VERSION:
# - If GTNH_PACK_VERSION is "latest-dev", only consider beta packs (path contains "/betas/").
# - If GTNH_PACK_VERSION is "latest", only consider non-beta packs (path does not contain "/betas/").
if [[ ($pack == *"/betas/"* && $GTNH_PACK_VERSION == "latest-dev") || ($pack != *"/betas/"* && $GTNH_PACK_VERSION == "latest") ]]; then
# Compare versions and update gtnh_download_path if pack is newer
# Check if the current version is unset or if the pack version is newer than the current version.
# This comparison uses version sorting to determine the latest version.
if [[ -z "$current_version" || "$(printf '%s\n' "$pack_version" "$current_version" | sort -V | tail -n 1)" == "$pack_version" ]]; then
# If the pack version is the same as the current version, prioritize based on release type.
# Full versions are preferred over RC (Release Candidate), and RC is preferred over beta.
# Within the same release type, higher numbered versions are preferred.
if [[ "$pack_version" == "$current_version" ]]; then
if [[ -z "$pack_release_type" || ("$pack_release_type" == "RC" && "$current_release_type" == "beta") ||
("$pack_release_type" == "$current_release_type" && "$(printf '%s\n' "$pack_release_type" "$current_release_type" | sort -V | tail -n 1)" == "$pack_release_type") ]]; then
debug "$current_version-$current_release_type is older than $pack_version-$pack_release_type! Update latest version to: $pack_version-$pack_release_type"
gtnh_download_path="$pack"
fi
else
# If the pack version is newer than the current version, set it as the download path.
debug "$current_version is older than $pack_version! Update latest version to: $pack_version"
gtnh_download_path="$pack"
fi
fi
else
if [[ "$pack_version" == "$GTNH_PACK_VERSION" || "$pack_version-$pack_release_type" == "$GTNH_PACK_VERSION" ]]; then
log "Found exact match $pack_version = $GTNH_PACK_VERSION! Select $pack_version for download."
gtnh_download_path="$pack"
break
fi
fi
done
} }
function deleteGTNHbackup(){ function deleteGTNHbackup(){
@@ -80,125 +93,80 @@ function deleteGTNHbackup(){
fi fi
} }
function downloadGTNH(){
local gtnh_download=""
base_dir=/data/.tmp/gtnh_base
debug "Creating temporary /data/.tmp/packs folder for GTNH download"
mkdir -p /data/.tmp/packs
trap 'rm -rf /data/.tmp' EXIT
log "Downloading $gtnh_download_path."
if ! gtnh_download=$(mc-image-helper get -o /data/.tmp/packs --output-filename --skip-up-to-date "$gtnh_download_path"); then
logError "Failed to download $gtnh_download_path"
exit 1
fi
debug "Downloaded GTNH server files to $gtnh_download"
# Unpacking Server files into temporary directory
log "Unpacking Server Files into $base_dir"
mkdir -p "${base_dir}"
extract "${gtnh_download}" "${base_dir}"
# Remove any eula file since container manages it
debug "Removing eula.txt from $base_dir"
rm -f "${base_dir}/eula.txt"
# recalculate the actual base directory of content
if ! base_dir=$(mc-image-helper find \
--max-depth=3 --type=directory --name=mods,config \
--only-shallowest --fail-no-matches --format '%h' \
"$base_dir"); then
logError "Unable to find content base of downloaded Server Files"
exit 1
fi
debug "Base directory of unpacked Server Files: $base_dir"
}
function updateGTNHresource(){
local resource="$1"
local new_resource="$2"
log "Trying to update $resource"
if [[ -z "$resource" ]]; then
logWarning "No resource specified for update"
return 0
fi
if [[ -e "$resource" ]]; then
log "Deleting existing resource: $resource"
if ! rm -rf "$resource"; then
logError "Failed to delete resource: $resource"
exit 1
fi
fi
if [[ -d "$new_resource" ]]; then
log "Copying $new_resource to /data"
if ! cp -r "$new_resource" "/data/"; then
logError "Failed to copy $new_resource to /data"
exit 1
fi
return 0
fi
if [[ -f "$new_resource" ]]; then
log "Copying $new_resource to /data"
if ! cp "$new_resource" "/data/"; then
logError "Failed to copy $new_resource to /data"
exit 1
fi
return 0
fi
logWarning "Resource update failed: $new_resource does not exist!"
return 0
}
function updateGTNH(){ function updateGTNH(){
# Get the current date and time # Get the current date and time
local current_datetime="" current_datetime=$(date +%Y-%m-%dT%H:%M)
current_datetime=$(date +%Y-%m-%dT+%H%M)
# Define folders and files to update # Define folders and files to update
# base_dir is already defined in handleGTNH function folders_to_update=("libraries" "mods" "resources" "scripts")
local folders_to_update=("libraries" "mods" "resources" "scripts") files_to_update=("lwjgl3ify-forgePatches.jar" "java9args.txt" "startserver-java9.bat" "startserver-java9.sh" "forge-1.7.10-10.13.4.1614-1.7.10-universal.jar" "startserver.bat" "startserver.sh" "server-icon.png")
local files_to_update=("lwjgl3ify-forgePatches.jar" "java9args.txt" "startserver-java9.bat" "startserver-java9.sh" "forge-1.7.10-10.13.4.1614-1.7.10-universal.jar" "startserver.bat" "startserver.sh" "server-icon.png") config_folder="config"
local config_folder="config" backup_folder="/data/gtnh-upgrade-${current_version}${current_release_type:+-$current_release_type}-$current_datetime"
local backup_folder="/data/gtnh-upgrade-$current_datetime" journey_map_folder="JourneyMapServer"
local journey_map_folder="JourneyMapServer"
# Delete specified folders if they exist
for folder in "${folders_to_update[@]}"; do
folder_path="/data/$folder"
if [[ -d "$folder_path" ]]; then
log "Deleting folder: $folder_path"
rm -rf "$folder_path"
fi
done
# Delete specific files if they exist
for file in "${files_to_update[@]}"; do
file_path="/data/$file"
if [[ -f "$file_path" ]]; then
log "Deleting file: $file_path"
rm -f "$file_path"
fi
done
# Backup the config folder # Backup the config folder
if [[ -d "/data/$config_folder" ]]; then if [[ -d "/data/$config_folder" ]]; then
log "Creating backup of /data/$config_folder at $backup_folder" log "Creating backup of /data/$config_folder at $backup_folder"
cp -r "/data/$config_folder" "$backup_folder" cp -r "/data/$config_folder" "$backup_folder"
log "Deleting original /data/$config_folder"
rm -rf "/data/$config_folder"
fi fi
# Update resources from unpacked server files to /data # Updating the required folders in data directory
for resource in "${folders_to_update[@]}" "$config_folder" "${files_to_update[@]}"; do for folder in "${folders_to_update[@]}" "$config_folder"; do
local resource_path="/data/$resource" if [[ -d "$base_dir/$folder" ]]; then
local new_resource_path="$base_dir/$resource" log "Copying $folder to /data"
cp -r "$base_dir/$folder" "/data/"
debug "Updating resource: $resource_path with new resource: $new_resource_path" else
updateGTNHresource "$resource_path" "$new_resource_path" logWarning "Folder $folder not found in the unzipped data!"
fi
done done
# Copy specific files to the /data directory
for file in "${files_to_update[@]}"; do
if [[ -f "$base_dir/$file" ]]; then
log "Copying $file to /data"
cp "$base_dir/$file" "/data/"
else
logWarning "File $file not found in the unzipped data!"
fi
done
# Ensure the config folder exists
if [[ ! -d "$config_folder" ]]; then
log "$config_folder does not exist. Creating it now."
mkdir -p "$config_folder"
fi
# Restore JourneyMapServer folder from backup # Restore JourneyMapServer folder from backup
if [[ -d "$backup_folder/$journey_map_folder" ]]; then if [[ -d "$backup_folder/$journey_map_folder" ]]; then
if [[ ! -d "/data/$config_folder" ]]; then log "Restoring $journey_map_folder to $config_folder"
log "/data/$config_folder folder does not exist. Creating it now." cp -r "$backup_folder/$journey_map_folder" "$config_folder/"
mkdir -p "/data/$config_folder"
fi
log "Restoring $journey_map_folder to /data/$config_folder"
cp -r "$backup_folder/$journey_map_folder" "/data/$config_folder/"
else else
logWarning "$journey_map_folder not found in backup!" logWarning "$journey_map_folder not found in backup!"
fi fi
# Copy the changelog file to /data # Copy the changelog file to /data
local gtnh_changelog_file=""
gtnh_changelog_file=$(mc-image-helper find --max-depth=1 --type=file --name=changelog*.md "$base_dir") gtnh_changelog_file=$(mc-image-helper find --max-depth=1 --type=file --name=changelog*.md "$base_dir")
if [[ -n "$gtnh_changelog_file" ]]; then if [[ -n "$gtnh_changelog_file" ]]; then
debug "Found changelog file: $gtnh_changelog_file"
log "Copying changelog file to /data" log "Copying changelog file to /data"
cp -f "$gtnh_changelog_file" /data/ cp -f "$gtnh_changelog_file" /data/
fi fi
@@ -215,19 +183,49 @@ function handleGTNH() {
deleteGTNHbackup deleteGTNHbackup
fi fi
if [[ -n "$GTNH_PACK_VERSION" ]] && isFalse "$SKIP_GTNH_UPDATE_CHECK" ; then if [[ -n $GTNH_PACK_VERSION ]] && isFalse "$SKIP_GTNH_UPDATE_CHECK" ; then
getGTNHdownloadPath getGTNHdownloadPath
if [[ -z $gtnh_download_path ]]; then
logError "Server files not found for GTNH_PACK_VERSION=$GTNH_PACK_VERSION! Download not possible!"
exit 1
fi
log "Server files located! Will proceed update $gtnh_download_path." log "Server files located! Will proceed update $gtnh_download_path."
# Decide if update or install is needed or not. # Decide if update or install is needed or not.
if [[ ! -f /data/.gtnh-version || "$(basename "$gtnh_download_path")" != "$(cat /data/.gtnh-version)" ]]; then if [[ ! -f /data/.gtnh-version || "$(basename "$gtnh_download_path")" != "$(cat /data/.gtnh-version)" ]]; then
log "Update/Install required: /data/.gtnh-version is missing or does not match the selected version $(basename "$gtnh_download_path")." log "Update/Install required: /data/.gtnh-version is missing or does not match the selected version $(basename "$gtnh_download_path")."
# Download and unpack GTNH server files mkdir -p /data/packs
downloadGTNH log "Downloading $gtnh_download_path."
log "GTNH server files downloaded and unpacked to $base_dir." if ! gtnh_download=$(mc-image-helper get -o /data/packs --output-filename --skip-up-to-date "$gtnh_download_path"); then
logError "Failed to download $gtnh_download_path"
exit 1
fi
# Unpacking Server files into temporary directory
log "Unpacking Server Files..."
original_base_dir=/data/.tmp/gtnh_base
base_dir=$original_base_dir
rm -rf "${base_dir}"
mkdir -p "${base_dir}"
extract "${gtnh_download}" "${base_dir}"
trap 'rm -rf /data/.tmp' EXIT
# Removing downloaded zip
rm -f "$gtnh_download"
# Remove any eula file since container manages it
rm -f "${base_dir}/eula.txt"
# recalculate the actual base directory of content
if ! base_dir=$(mc-image-helper find \
--max-depth=3 --type=directory --name=mods,config \
--only-shallowest --fail-no-matches --format '%h' \
"$base_dir"); then
logError "Unable to find content base of downloaded Server Files"
exit 1
fi
# Split installation from update path. Check for version file. # Split installation from update path. Check for version file.
if [[ -f /data/.gtnh-version ]]; then if [[ -f /data/.gtnh-version ]]; then
@@ -237,12 +235,10 @@ function handleGTNH() {
log "No .gtnh-version file detected! Assuming no old server exists. Proceed installing new server..." log "No .gtnh-version file detected! Assuming no old server exists. Proceed installing new server..."
cp -R -f "${base_dir}"/* /data cp -R -f "${base_dir}"/* /data
fi fi
# Update .gtnh-version # Update .gtnh-version
basename "$gtnh_download_path" > /data/.gtnh-version basename "$gtnh_download_path" > /data/.gtnh-version
# Cleaning up
# Cleaning up temporary files rm -rf "$original_base_dir"
rm -rf /data/.tmp
else else
log "No update required: /data/.gtnh-version matches the selected version $(basename "$gtnh_download_path")." log "No update required: /data/.gtnh-version matches the selected version $(basename "$gtnh_download_path")."
+6 -20
View File
@@ -11,26 +11,17 @@ handleDebugMode
: "${PAPER_DOWNLOAD_URL:=}" : "${PAPER_DOWNLOAD_URL:=}"
: "${PAPER_CUSTOM_JAR:=}" : "${PAPER_CUSTOM_JAR:=}"
: "${PAPER_CONFIG_DEFAULTS_REPO:=${PAPER_CONFIG_REPO:=https://raw.githubusercontent.com/Shonz1/minecraft-default-configs/main}}" : "${PAPER_CONFIG_DEFAULTS_REPO:=${PAPER_CONFIG_REPO:=https://raw.githubusercontent.com/Shonz1/minecraft-default-configs/main}}"
: "${CLEAN_SERVER_LIBRARIES:=true}"
resultsFile=/data/.paper.env resultsFile=/data/.paper.env
if [[ $PAPER_CUSTOM_JAR ]]; then if [[ $PAPER_CUSTOM_JAR ]]; then
export SERVER="$PAPER_CUSTOM_JAR" export SERVER="$PAPER_CUSTOM_JAR"
elif [[ $PAPER_DOWNLOAD_URL ]]; then elif [[ $PAPER_DOWNLOAD_URL ]]; then
if ! mc-image-helper install-paper \
args=( --output-directory=/data \
--output-directory=/data --results-file="$resultsFile" \
--results-file="$resultsFile" --url="$PAPER_DOWNLOAD_URL"; then
--url="$PAPER_DOWNLOAD_URL" logError "Failed to download from custom PaperMC URL"
) exit 1
if isTrue $CLEAN_SERVER_LIBRARIES; then
args+=(--clean-libraries)
fi
if ! mc-image-helper install-paper "${args[@]}"; then
logError "Failed to download from custom PaperMC URL"
exit 1
fi fi
applyResultsFile ${resultsFile} applyResultsFile ${resultsFile}
else else
@@ -44,11 +35,6 @@ else
if [[ $PAPER_BUILD ]]; then if [[ $PAPER_BUILD ]]; then
args+=(--build="$PAPER_BUILD") args+=(--build="$PAPER_BUILD")
fi fi
if isTrue $CLEAN_SERVER_LIBRARIES; then
args+=(--clean-libraries)
fi
if ! mc-image-helper install-paper "${args[@]}"; then if ! mc-image-helper install-paper "${args[@]}"; then
logError "Failed to download $PAPER_PROJECT" logError "Failed to download $PAPER_PROJECT"
exit 1 exit 1
+4 -13
View File
@@ -5,7 +5,6 @@ IFS=$'\n\t'
: "${PURPUR_BUILD:=LATEST}" : "${PURPUR_BUILD:=LATEST}"
: "${PURPUR_DOWNLOAD_URL:=}" : "${PURPUR_DOWNLOAD_URL:=}"
: "${PURPUR_CONFIG_REPO:=}" : "${PURPUR_CONFIG_REPO:=}"
: "${CLEAN_SERVER_LIBRARIES:=true}"
# shellcheck source=start-utils # shellcheck source=start-utils
. "$(dirname "$0")/start-utils" . "$(dirname "$0")/start-utils"
@@ -14,15 +13,10 @@ isDebugging && set -x
resultsFile=/data/.purpur.env resultsFile=/data/.purpur.env
if [[ $PURPUR_DOWNLOAD_URL ]]; then if [[ $PURPUR_DOWNLOAD_URL ]]; then
args=( if ! mc-image-helper install-purpur \
--output-directory=/data --output-directory=/data \
--results-file="$resultsFile" --results-file="$resultsFile" \
--url="${PURPUR_DOWNLOAD_URL}" --url="${PURPUR_DOWNLOAD_URL}"; then
)
if isTrue "$CLEAN_SERVER_LIBRARIES"; then
args+=(--clean-libraries)
fi
if ! mc-image-helper install-purpur "${args[@]}"; then
logError "Failed to download from custom Purpur URL" logError "Failed to download from custom Purpur URL"
exit 1 exit 1
fi fi
@@ -35,9 +29,6 @@ else
if [[ $PURPUR_BUILD ]]; then if [[ $PURPUR_BUILD ]]; then
args+=(--build="$PURPUR_BUILD") args+=(--build="$PURPUR_BUILD")
fi fi
if isTrue "$CLEAN_SERVER_LIBRARIES"; then
args+=(--clean-libraries)
fi
if ! mc-image-helper install-purpur "${args[@]}"; then if ! mc-image-helper install-purpur "${args[@]}"; then
logError "Failed to download Purpur" logError "Failed to download Purpur"
exit 1 exit 1
-3
View File
@@ -481,9 +481,6 @@ fi
if [[ ${STOP_SERVER_ANNOUNCE_DELAY} ]]; then if [[ ${STOP_SERVER_ANNOUNCE_DELAY} ]]; then
mcServerRunnerArgs+=(--stop-server-announce-delay "${STOP_SERVER_ANNOUNCE_DELAY}s") mcServerRunnerArgs+=(--stop-server-announce-delay "${STOP_SERVER_ANNOUNCE_DELAY}s")
fi fi
if [[ ${STOP_SERVER_DELAY_COMMAND} ]]; then
mcServerRunnerArgs+=(--stop-server-delay-command "${STOP_SERVER_DELAY_COMMAND}s")
fi
if isTrue "${ENABLE_SSH}"; then if isTrue "${ENABLE_SSH}"; then
mcServerRunnerArgs+=(--remote-console) mcServerRunnerArgs+=(--remote-console)
fi fi
-10
View File
@@ -50,16 +50,6 @@ function handlePackwiz() {
logError "Failed to run packwiz installer" logError "Failed to run packwiz installer"
exit 1 exit 1
fi fi
# packwiz may have just downloaded/updated the env file referenced by
# LOAD_ENV_FROM_FILE. The initial load in start-configuration happened
# before this point, so re-load it now to pick up the pack's values for
# the remaining setup stages (server.properties, JVM args, etc.).
if [[ ${LOAD_ENV_FROM_FILE:-} ]]; then
if ! loadEnvFromFile "${LOAD_ENV_FROM_FILE}"; then
exit 1
fi
fi
fi fi
} }
+3 -133
View File
@@ -26,117 +26,6 @@ function applyResultsFile() {
set +a set +a
} }
function loadEnvFromFile() {
local source=${1?Missing required source argument}
local downloaded=
if isURL "$source"; then
mkdir -p /data/.tmp
downloaded=$(mktemp -p /data/.tmp)
log "Downloading env file from $source"
if ! get -o "$downloaded" "$source"; then
logError "Failed to download env file from $source"
rm -f "$downloaded"
return 1
fi
log "Loading env vars from $source"
applyResultsFile "$downloaded"
rm -f "$downloaded"
elif [ -f "$source" ]; then
log "Loading env vars from $source"
applyResultsFile "$source"
else
logError "Env file not found: $source"
return 1
fi
}
function loadEnvFromArchive() {
local source=${1?Missing required source argument}
local entry=${2:-.env}
local archive=
local downloaded=
local tmpdir
local rc=0
mkdir -p /data/.tmp
if isURL "$source"; then
downloaded=$(mktemp -p /data/.tmp)
log "Downloading archive from $source"
if ! get -o "$downloaded" "$source"; then
logError "Failed to download archive from $source"
rm -f "$downloaded"
return 1
fi
archive=$downloaded
elif [ -f "$source" ]; then
archive=$source
else
logError "Archive not found: $source"
return 1
fi
tmpdir=$(mktemp -d -p /data/.tmp)
if extract "$archive" "$tmpdir" "$entry" && [ -f "$tmpdir/$entry" ]; then
log "Loading env vars from '$entry' in $source"
applyResultsFile "$tmpdir/$entry"
else
logError "Failed to load env entry '$entry' from $source"
rc=1
fi
rm -rf "$tmpdir"
[[ -n "$downloaded" ]] && rm -f "$downloaded"
return $rc
}
function loadEnvFromGenericPack() {
: "${GENERIC_PACKS:=${GENERIC_PACK:-}}"
: "${GENERIC_PACKS_PREFIX:=}"
: "${GENERIC_PACKS_SUFFIX:=}"
if [[ -z "${GENERIC_PACKS}" ]]; then
logWarning "LOAD_ENV_FROM_GENERIC_PACK is set but GENERIC_PACK(S) is empty"
return 0
fi
mkdir -p /data/.tmp
IFS=',' read -ra packs <<< "${GENERIC_PACKS}"
local loaded=0
local pack packEntry packFile tmpdir
for packEntry in "${packs[@]}"; do
pack="${GENERIC_PACKS_PREFIX}${packEntry}${GENERIC_PACKS_SUFFIX}"
if isURL "$pack"; then
mkdir -p /data/packs
if ! packFile=$(get -o /data/packs --output-filename --skip-up-to-date "$pack"); then
logError "Failed to download generic pack $pack"
return 1
fi
else
packFile=$pack
fi
if [[ ! -f "$packFile" ]]; then
logError "Generic pack not found: $packFile"
return 1
fi
tmpdir=$(mktemp -d -p /data/.tmp)
# Packs without a .env are valid — silently skip; the unpack step still applies them.
if extract "$packFile" "$tmpdir" .env 2>/dev/null && [ -f "$tmpdir/.env" ]; then
log "Loading env vars from .env in $pack"
applyResultsFile "$tmpdir/.env"
loaded=$((loaded + 1))
fi
rm -rf "$tmpdir"
done
if (( loaded == 0 )); then
logWarning "LOAD_ENV_FROM_GENERIC_PACK is set but no pack in GENERIC_PACK(S) contained a .env"
fi
}
function join_by() { function join_by() {
local d=$1 local d=$1
shift shift
@@ -236,12 +125,6 @@ function logn() {
echo -n "[init] $*" echo -n "[init] $*"
} }
# Use as
# cmd | applyLogPrefix
function applyLogPrefix() {
sed 's/^/[init] /'
}
function log() { function log() {
local oldState local oldState
# The return status when listing options is zero if all optnames are enabled, non- zero otherwise. # The return status when listing options is zero if all optnames are enabled, non- zero otherwise.
@@ -556,30 +439,17 @@ function isType() {
function extract() { function extract() {
src=${1?} src=${1?}
destDir=${2?} destDir=${2?}
shift 2
# remaining args are paths within the archive to extract; if none, extract everything
type=$(file -b --mime-type "${src}") type=$(file -b --mime-type "${src}")
if [[ "$type" == application/octet-stream ]]; then
logWarning "Detected non-specific file type $type for $src"
case "$src" in
*.zip)
log "Assuming zip from extension"
type=application/zip
;;
# otherwise fall through to
esac
fi
case "${type}" in case "${type}" in
application/zip) application/zip)
unzip -o -q -d "${destDir}" "${src}" "$@" unzip -o -q -d "${destDir}" "${src}"
;; ;;
application/x-tar | application/gzip | application/x-gzip | application/x-bzip2) application/x-tar | application/gzip | application/x-gzip | application/x-bzip2)
tar -C "${destDir}" -xf "${src}" "$@" tar -C "${destDir}" -xf "${src}"
;; ;;
application/zstd | application/x-zstd) application/zstd | application/x-zstd)
tar -C "${destDir}" --use-compress-program=unzstd -xf "${src}" "$@" tar -C "${destDir}" --use-compress-program=unzstd -xf "${src}"
;; ;;
*) *)
logError "Unsupported archive type: $type" logError "Unsupported archive type: $type"
@@ -1,17 +0,0 @@
services:
mc:
build:
# ...or wherever you cloned the docker-minecraft-server repo
context: ../../..
args:
MC_HELPER_VERSION: 1.56.0
environment:
EULA: true
TYPE: "FABRIC"
MODRINTH_PROJECTS: |
fabric-api
pl3xmap?:beta
ports:
- "25565:25565/tcp"
volumes:
- ./data:/data
@@ -1,18 +0,0 @@
services:
mc:
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
environment:
EULA: "true"
SETUP_ONLY: "true"
LOAD_ENV_FROM_ARCHIVE: /test/load-env.zip
MOTD: from-compose
LOG_TIMESTAMP: "true"
DEBUG: "true"
# the following are only used to speed up test execution
TYPE: CUSTOM
CUSTOM_SERVER: /servers/fake.jar
VERSION: 1.18.1
volumes:
- ./data:/data
- ./load-env.zip:/test/load-env.zip
- ./fake.jar:/servers/fake.jar
@@ -1 +0,0 @@
mc-image-helper assert propertyEquals --file=server.properties --property=motd --expect=from-archive
@@ -1,18 +0,0 @@
services:
mc:
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
environment:
EULA: "true"
SETUP_ONLY: "true"
LOAD_ENV_FROM_FILE: /test/load-env.env
MOTD: from-compose
LOG_TIMESTAMP: "true"
DEBUG: "true"
# the following are only used to speed up test execution
TYPE: CUSTOM
CUSTOM_SERVER: /servers/fake.jar
VERSION: 1.18.1
volumes:
- ./data:/data
- ./load-env.env:/test/load-env.env
- ./fake.jar:/servers/fake.jar
@@ -1,2 +0,0 @@
# Loaded by LOAD_ENV_FROM_FILE during start-configuration
MOTD=from-env-file
@@ -1 +0,0 @@
mc-image-helper assert propertyEquals --file=server.properties --property=motd --expect=from-env-file
@@ -1,19 +0,0 @@
services:
mc:
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
environment:
EULA: "true"
SETUP_ONLY: "true"
GENERIC_PACK: /packs/pack.zip
LOAD_ENV_FROM_GENERIC_PACK: "true"
MOTD: from-compose
LOG_TIMESTAMP: "true"
DEBUG: "true"
# the following are only used to speed up test execution
TYPE: CUSTOM
CUSTOM_SERVER: /servers/fake.jar
VERSION: 1.18.1
volumes:
- ./data:/data
- ./pack.zip:/packs/pack.zip
- ./fake.jar:/servers/fake.jar
@@ -1,2 +0,0 @@
mc-image-helper assert propertyEquals --file=server.properties --property=motd --expect=from-generic-pack
mc-image-helper assert fileExists config/dummy.yml
+1 -1
View File
@@ -46,7 +46,7 @@ setupOnlyMinecraftTest(){
start=$(date +%s) start=$(date +%s)
status=PASSED status=PASSED
verify= verify=
if ! logs=$(docker compose run --rm -e SETUP_ONLY=true -e DEBUG="${DEBUG:-false}" -e GH_TOKEN="${GH_TOKEN:-}" mc 2>&1); then if ! logs=$(docker compose run --rm -e SETUP_ONLY=true -e DEBUG="${DEBUG:-false}" mc 2>&1); then
status=FAILED status=FAILED
outputContainerLog "$logs" outputContainerLog "$logs"
result=1 result=1