mirror of
https://github.com/itzg/docker-minecraft-server.git
synced 2026-08-17 20:53:17 +00:00
Compare commits
5
Commits
3302bdb3cb
...
2026.7.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd2c5628f2 | ||
|
|
0a445cd8db | ||
|
|
537a3e43fe | ||
|
|
17d7f01267 | ||
|
|
591f37bfa5 |
@@ -6,6 +6,8 @@ on:
|
||||
jobs:
|
||||
auto-release:
|
||||
runs-on: ubuntu-latest
|
||||
# If forked, changed to your username to enable auto-releases
|
||||
if: github.repository_owner == 'itzg'
|
||||
permissions:
|
||||
# allow for creating releases/tags
|
||||
contents: write
|
||||
|
||||
+19
-25
@@ -45,12 +45,12 @@ jobs:
|
||||
baseImage: eclipse-temurin:25-jre-noble
|
||||
platforms: linux/amd64,linux/arm64,linux/riscv64
|
||||
mcVersion: latest
|
||||
# forked build that include riscv64
|
||||
knockdRepoOrg: Opvolger/knock
|
||||
- variant: java25-alpine
|
||||
baseImage: eclipse-temurin:25-jre-alpine
|
||||
platforms: linux/amd64,linux/arm64
|
||||
mcVersion: latest
|
||||
# For GLIBC_2.34 support (and Alpine)
|
||||
knockdRepoOrg: Metalcape/knock
|
||||
- variant: java25-jdk
|
||||
baseImage: eclipse-temurin:25
|
||||
platforms: linux/amd64,linux/arm64
|
||||
@@ -68,23 +68,17 @@ jobs:
|
||||
baseImage: eclipse-temurin:21-jre-alpine
|
||||
platforms: linux/amd64,linux/arm64
|
||||
mcVersion: 1.21.11
|
||||
# For GLIBC_2.34 support (and Alpine)
|
||||
knockdRepoOrg: Metalcape/knock
|
||||
# JAVA 17:
|
||||
- variant: java17
|
||||
# jammy doesn't work until minecraft updates to https://github.com/netty/netty/issues/12343
|
||||
baseImage: eclipse-temurin:17-jre-focal
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||
mcVersion: 1.20.4
|
||||
# For GLIBC_2.34 support (and Alpine)
|
||||
knockdRepoOrg: Metalcape/knock
|
||||
# JAVA 16
|
||||
- variant: java16
|
||||
baseImage: adoptopenjdk:16-jre-hotspot
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||
mcVersion: 1.16.5
|
||||
# For GLIBC_2.34 support
|
||||
knockdRepoOrg: Metalcape/knock
|
||||
# Pin version for pre-Java 17
|
||||
mcHelperVersion: 1.51.3-java8
|
||||
# JAVA 11
|
||||
@@ -92,8 +86,6 @@ jobs:
|
||||
baseImage: adoptopenjdk:11-jre-hotspot
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||
mcVersion: 1.16.4
|
||||
# For GLIBC_2.34 support
|
||||
knockdRepoOrg: Metalcape/knock
|
||||
# Pin version for pre-Java 17
|
||||
mcHelperVersion: 1.51.3-java8
|
||||
# JAVA 8: NOTE: Unable to go past 8u312 because of Forge dependencies
|
||||
@@ -101,22 +93,22 @@ jobs:
|
||||
baseImage: eclipse-temurin:8u312-b07-jre-focal
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||
mcVersion: 1.12.2
|
||||
# For GLIBC_2.34 support
|
||||
knockdRepoOrg: Metalcape/knock
|
||||
# Pin version for Java 8, also be sure to set in verify-pr.yml
|
||||
mcHelperVersion: 1.51.3-java8
|
||||
- variant: java8-jdk
|
||||
baseImage: eclipse-temurin:8u312-b07-jdk-focal
|
||||
platforms: linux/amd64,linux/arm64
|
||||
mcVersion: 1.12.2
|
||||
# For GLIBC_2.34 support
|
||||
knockdRepoOrg: Metalcape/knock
|
||||
# Pin version for Java 8, also be sure to set in verify-pr.yml
|
||||
mcHelperVersion: 1.51.3-java8
|
||||
env:
|
||||
# Assume they line up, but when forked change to your Docker Hub username
|
||||
DOCKER_HUB_ORG: ${{ github.repository_owner }}
|
||||
IMAGE_TO_TEST: "${{ github.repository_owner }}/minecraft-server:test-${{ matrix.variant }}-${{ github.run_id }}"
|
||||
HAS_IMAGE_REPO_ACCESS: ${{ secrets.DOCKER_USER != '' && secrets.DOCKER_PASSWORD != '' }}
|
||||
MAIN_VARIANT: java25
|
||||
PUSH: ${{ github.repository_owner == 'itzg' }}
|
||||
IMAGE_AUTHOR: "Geoff Bourne <itzgeoff@gmail.com>"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -129,10 +121,8 @@ jobs:
|
||||
id: meta
|
||||
uses: docker/metadata-action@v6.2.0
|
||||
with:
|
||||
# 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.
|
||||
images: |
|
||||
${{ github.repository_owner }}/minecraft-server
|
||||
${{ env.DOCKER_HUB_ORG }}/minecraft-server
|
||||
ghcr.io/${{ github.repository_owner }}/minecraft-server
|
||||
tags: |
|
||||
# Apply the variant as a moving tag for most recent commit per variant
|
||||
@@ -154,7 +144,7 @@ jobs:
|
||||
flavor: |
|
||||
latest=${{ matrix.variant == env.MAIN_VARIANT && github.ref_name == github.event.repository.default_branch }}
|
||||
labels: |
|
||||
org.opencontainers.image.authors=Geoff Bourne <itzgeoff@gmail.com>
|
||||
org.opencontainers.image.authors=${{ env.IMAGE_AUTHOR }}
|
||||
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
@@ -210,13 +200,16 @@ jobs:
|
||||
platforms: ${{ matrix.platforms }}
|
||||
push: >
|
||||
${{
|
||||
github.ref_type == 'tag'
|
||||
|| github.ref_name == github.event.repository.default_branch
|
||||
|| startsWith(github.ref_name, 'test/')
|
||||
|| ( github.event_name == 'pull_request'
|
||||
&& env.HAS_IMAGE_REPO_ACCESS
|
||||
&& contains(github.event.pull_request.labels.*.name, 'ci/push-image')
|
||||
)
|
||||
env.PUSH &&
|
||||
(
|
||||
github.ref_type == 'tag'
|
||||
|| github.ref_name == github.event.repository.default_branch
|
||||
|| startsWith(github.ref_name, 'test/')
|
||||
|| ( github.event_name == 'pull_request'
|
||||
&& env.HAS_IMAGE_REPO_ACCESS
|
||||
&& contains(github.event.pull_request.labels.*.name, 'ci/push-image')
|
||||
)
|
||||
)
|
||||
}}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
# ensure latest base image is used
|
||||
@@ -233,5 +226,6 @@ jobs:
|
||||
REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}
|
||||
${{ matrix.mcHelperVersion && format('MC_HELPER_VERSION={0}', matrix.mcHelperVersion) }}
|
||||
${{ matrix.knockdRepoOrg && format('KNOCKD_REPO_ORG={0}', matrix.knockdRepoOrg) }}
|
||||
IMAGE_AUTHOR=${{ env.IMAGE_AUTHOR }}
|
||||
cache-from: type=gha,scope=${{ matrix.variant }}
|
||||
cache-to: type=gha,mode=max,scope=${{ matrix.variant }}
|
||||
|
||||
@@ -16,6 +16,7 @@ jobs:
|
||||
discord:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
if: github.repository_owner == 'itzg'
|
||||
steps:
|
||||
- name: on-publish
|
||||
if: github.event_name == 'release' && github.event.action == 'published'
|
||||
|
||||
@@ -13,6 +13,7 @@ on:
|
||||
- labeled
|
||||
jobs:
|
||||
notify:
|
||||
if: github.repository_owner == 'itzg'
|
||||
uses: itzg/github-workflows/.github/workflows/issues-notify-discord.yml@main
|
||||
with:
|
||||
triageLabel: 'status/needs triage'
|
||||
@@ -7,6 +7,7 @@ on:
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.repository_owner == 'itzg'
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ ARG EXTRA_DNF_PACKAGES=""
|
||||
ARG EXTRA_ALPINE_PACKAGES=""
|
||||
ARG FORCE_INSTALL_PACKAGES=1
|
||||
ARG KNOCKD_VERSION=0.8.1
|
||||
ARG KNOCKD_REPO_ORG=Opvolger/knock
|
||||
ARG KNOCKD_REPO_ORG=Metalcape/knock
|
||||
RUN --mount=target=/build,source=build \
|
||||
TARGET=${TARGETARCH}${TARGETVARIANT} \
|
||||
/build/run.sh install-packages
|
||||
|
||||
@@ -35,6 +35,7 @@ apk add --no-cache -U \
|
||||
libcap \
|
||||
numactl \
|
||||
jattach \
|
||||
gcompat \
|
||||
${EXTRA_ALPINE_PACKAGES}
|
||||
|
||||
# Download and install patched knockd
|
||||
|
||||
@@ -6,7 +6,7 @@ A specific file can be omitted from each reference to allow for auto-selecting t
|
||||
|
||||
!!! info "CurseForge API key usage"
|
||||
|
||||
A CurseForge API key must be allocated and set with `CF_API_KEY` (or `CF_API_KEY_FILE`) [as described here](../types-and-platforms/mod-platforms/auto-curseforge.md#api-key).
|
||||
A CurseForge API key is _now_ included by this image; however, you can always supply your own instead. A CurseForge API key can be allocated and set with `CF_API_KEY` (or `CF_API_KEY_FILE`) [as described here](../types-and-platforms/mod-platforms/auto-curseforge.md#api-key).
|
||||
|
||||
## Project-file references
|
||||
|
||||
|
||||
@@ -151,6 +151,26 @@ GENERIC_PACKS_SUFFIX=.zip
|
||||
|
||||
would expand to `https://cdn.example.org/configs-v9.0.1.zip,https://cdn.example.org/mods-v4.3.6.zip`.
|
||||
|
||||
### Generic packs from an OCI registry
|
||||
|
||||
An entry can also reference a pack stored as an [OCI](https://opencontainers.org/) artifact in a container registry by prefixing it with `oci://`. The reference may use a tag or an immutable `@sha256:` digest:
|
||||
|
||||
```
|
||||
GENERIC_PACKS=oci://ghcr.io/itzg/oci-modpack-template/tech:latest,oci://ghcr.io/itzg/oci-modpack-template/magic:latest
|
||||
```
|
||||
|
||||
OCI, URL, and local-path entries can be mixed in the same list and are applied in the order given. Each artifact's layers are pulled into a content-addressed cache under `/data/packs/oci`, so a digest already on disk (for example a base layer shared between packs) is not downloaded again. `GENERIC_PACKS_PREFIX`/`GENERIC_PACKS_SUFFIX`, `GENERIC_PACKS_DISABLE_MODS`, and the update/checksum behaviour below all apply to OCI entries exactly as they do to URLs.
|
||||
|
||||
The artifact must be a Minecraft modpack artifact (artifact type `application/vnd.itzg.minecraft.modpack.v1+json` with `…modpack.layer.v1.tar+gzip` layers); any other reference is rejected before its contents touch `/data`. Validation and registry authentication are handled by `mc-image-helper`.
|
||||
|
||||
For a private registry, point `GENERIC_PACKS_OCI_AUTH_FILE` at a registry login file (the `auth.json`/`config.json` produced by `docker login`, `podman login`, etc.):
|
||||
|
||||
```
|
||||
GENERIC_PACKS_OCI_AUTH_FILE=/run/secrets/registry-auth.json
|
||||
```
|
||||
|
||||
When it is unset, a credentials file at `~/.config/containers/auth.json` or `~/.docker/config.json` is used if present, otherwise the pull is anonymous.
|
||||
|
||||
If applying large generic packs, the update can be time-consuming. To skip the update set `SKIP_GENERIC_PACK_UPDATE_CHECK` to "true". Conversely, the generic pack(s) can be forced to be applied by setting `FORCE_GENERIC_PACK_UPDATE` to "true".
|
||||
|
||||
The most time-consuming portion of the generic pack update is generating and comparing the SHA1 checksum. To skip the checksum generation, set `SKIP_GENERIC_PACK_CHECKSUM` to "true".
|
||||
|
||||
@@ -79,13 +79,11 @@ Pass a page URL to the modpack or a specific file with `CF_PAGE_URL` such as the
|
||||
environment:
|
||||
# ...
|
||||
MODPACK_PLATFORM: AUTO_CURSEFORGE
|
||||
# allocate from https://console.curseforge.com/ and set in .env file
|
||||
CF_API_KEY: ${CF_API_KEY}
|
||||
CF_PAGE_URL: https://www.curseforge.com/minecraft/modpacks/all-the-mods-8
|
||||
```
|
||||
|
||||
```title="Using docker run"
|
||||
docker run -e CF_API_KEY=${CF_API_KEY} -e TYPE=AUTO_CURSEFORGE -e CF_PAGE_URL=https://www.curseforge.com/minecraft/modpacks/all-the-mods-8
|
||||
docker run -e TYPE=AUTO_CURSEFORGE -e CF_PAGE_URL=https://www.curseforge.com/minecraft/modpacks/all-the-mods-8
|
||||
```
|
||||
|
||||
Instead of a URL, the modpack slug can be provided as `CF_SLUG`. The slug is the short identifier visible in the URL after "/modpacks/", such as
|
||||
@@ -98,13 +96,11 @@ Instead of a URL, the modpack slug can be provided as `CF_SLUG`. The slug is the
|
||||
environment:
|
||||
# ...
|
||||
MODPACK_PLATFORM: AUTO_CURSEFORGE
|
||||
# allocate from https://console.curseforge.com/ and set in .env file
|
||||
CF_API_KEY: ${CF_API_KEY}
|
||||
CF_SLUG: all-the-mods-8
|
||||
```
|
||||
|
||||
```title="Using docker run"
|
||||
docker run -e CF_API_KEY=${CF_API_KEY} -e TYPE=AUTO_CURSEFORGE -e CF_SLUG=all-the-mods-8
|
||||
docker run -e TYPE=AUTO_CURSEFORGE -e CF_SLUG=all-the-mods-8
|
||||
```
|
||||
|
||||
### Pinning modpack and mod loader versions
|
||||
@@ -148,7 +144,6 @@ By default, AUTO_CURSEFORGE will use the exact modloader version declared by the
|
||||
```yaml
|
||||
environment:
|
||||
MODPACK_PLATFORM: AUTO_CURSEFORGE
|
||||
CF_API_KEY: ${CF_API_KEY}
|
||||
CF_SLUG: all-the-mods-8
|
||||
CF_MOD_LOADER_VERSION: "43.4.22"
|
||||
```
|
||||
@@ -197,8 +192,6 @@ If you wish to use an unpublished modpack zip, set the container path to the fil
|
||||
environment:
|
||||
EULA: true
|
||||
MODPACK_PLATFORM: AUTO_CURSEFORGE
|
||||
# allocate from https://console.curseforge.com/ and set in .env file
|
||||
CF_API_KEY: ${CF_API_KEY}
|
||||
CF_MODPACK_MANIFEST: /manifests/manifest.json
|
||||
CF_SLUG: "custom"
|
||||
volumes:
|
||||
|
||||
@@ -33,6 +33,10 @@ if (( $(mc-image-helper java-release) >= 17 )); then
|
||||
export MC_IMAGE_HELPER_OPTS
|
||||
fi
|
||||
|
||||
if [[ $(getDistro) == alpine ]]; then
|
||||
export LD_PRELOAD=/lib/libgcompat.so.0
|
||||
fi
|
||||
|
||||
export HOME=/data
|
||||
|
||||
log "Running as uid=$(id -u) gid=$(id -g) with /data as '$(ls -lnd /data)'"
|
||||
|
||||
@@ -181,7 +181,38 @@ function handleGenericPacks() {
|
||||
packFiles=()
|
||||
for packEntry in "${packs[@]}"; do
|
||||
pack="${GENERIC_PACKS_PREFIX}${packEntry}${GENERIC_PACKS_SUFFIX}"
|
||||
if isURL "${pack}"; then
|
||||
if isOCIRef "${pack}"; then
|
||||
# All OCI refs share one staging dir so layers common to multiple
|
||||
# sibling artifacts (the point of layered distribution) are pulled
|
||||
# exactly once across all of GENERIC_PACKS.
|
||||
mkdir -p /data/packs/oci /data/.tmp
|
||||
log "Pulling OCI generic pack from $pack"
|
||||
# A list file is used rather than stdout because mc-image-helper INFO
|
||||
# logs share that stream; it holds one absolute layer path per line in
|
||||
# apply order.
|
||||
layerListFile=$(mktemp -p /data/.tmp)
|
||||
ociArgs=(install-oci-pack
|
||||
--ref "$pack"
|
||||
--output-directory /data/packs/oci
|
||||
--filename-strategy digest
|
||||
--layer-list-file "$layerListFile")
|
||||
if [[ "${GENERIC_PACKS_OCI_AUTH_FILE:-}" ]]; then
|
||||
ociArgs+=(--auth-file "${GENERIC_PACKS_OCI_AUTH_FILE}")
|
||||
fi
|
||||
if ! mc-image-helper "${ociArgs[@]}"; then
|
||||
logError "Failed to pull OCI generic pack $pack"
|
||||
logError "(OCI generic packs require mc-image-helper with install-oci-pack support)"
|
||||
rm -f "$layerListFile"
|
||||
exit 2
|
||||
fi
|
||||
mapfile -t ociLayers < "$layerListFile"
|
||||
rm -f "$layerListFile"
|
||||
if [ ${#ociLayers[@]} -eq 0 ]; then
|
||||
logError "OCI generic pack $pack resolved to zero layers"
|
||||
exit 2
|
||||
fi
|
||||
packFiles+=("${ociLayers[@]}")
|
||||
elif isURL "${pack}"; then
|
||||
mkdir -p /data/packs
|
||||
log "Downloading generic pack from $pack"
|
||||
if ! outfile=$(get -o /data/packs --output-filename --skip-up-to-date "$pack"); then
|
||||
|
||||
@@ -173,6 +173,12 @@ function isURL() {
|
||||
[[ $value =~ ^(https?|ftp):// ]]
|
||||
}
|
||||
|
||||
function isOCIRef() {
|
||||
local value=$1
|
||||
|
||||
[[ $value =~ ^oci:// ]]
|
||||
}
|
||||
|
||||
function isValidFileURL() {
|
||||
suffix=${1:?Missing required suffix arg}
|
||||
url=${2:?Missing required url arg}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
services:
|
||||
mc:
|
||||
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||
environment:
|
||||
EULA: "true"
|
||||
SETUP_ONLY: "true"
|
||||
# two OCI packs that share a common base layer; the shared blob is
|
||||
# pulled into /data/packs/oci once and reused for the second pack
|
||||
GENERIC_PACKS: oci://ghcr.io/itzg/oci-modpack-template/tech:latest,oci://ghcr.io/itzg/oci-modpack-template/magic:latest
|
||||
LOG_TIMESTAMP: "true"
|
||||
# the following are only used to speed up test execution
|
||||
TYPE: CUSTOM
|
||||
CUSTOM_SERVER: /servers/fake.jar
|
||||
VERSION: 1.18.1
|
||||
DEBUG: "true"
|
||||
volumes:
|
||||
- ./data:/data
|
||||
- ./fake.jar:/servers/fake.jar
|
||||
@@ -0,0 +1 @@
|
||||
[[ $EXTENDED_TESTS ]] || exit 1
|
||||
@@ -0,0 +1,7 @@
|
||||
set -e
|
||||
# OCI layers were cached
|
||||
[ -d /data/packs/oci ]
|
||||
compgen -G "/data/packs/oci/sha256:*" > /dev/null
|
||||
# pack content was extracted and applied to /data
|
||||
[ -d /data/mods ]
|
||||
compgen -G "/data/mods/*" > /dev/null
|
||||
Reference in New Issue
Block a user