docker-minecraft-server 镜像构建实战:内联 Dockerfile 扩包、自定义 Java 基础镜像与多架构构建
【免费下载链接】docker-minecraft-serverDocker image that provides a Minecraft Server for Java Edition that automatically installs/upgrades versions, modloaders, modpacks and more at startup项目地址: https://gitcode.com/GitHub_Trending/do/docker-minecraft-server
本篇技术指南围绕 docker-minecraft-server 官方文档中的镜像构建(building)能力展开:如何在已有镜像之上用 Compose 内联 Dockerfile 追加系统依赖、如何通过BASE_IMAGE构建参数替换 Java 基础镜像、如何用 buildx 构建多架构镜像,以及通过哪三个构建参数为不同发行版注入额外软件包。读完后你将掌握从源码级视角理解该镜像构建体系(Dockerfile 与各发行版的安装脚本)的全部细节,并能独立完成自定义镜像的构建与发布。
适用前提:这是一项“高级用法”
官方文档在 docs/misc/building.md 中明确提示:自定义镜像构建是一项仅面向高级用户的能力,绝大多数玩家并不需要用到它。它只在两种罕见场景下才有价值:
- 确实需要某个特定的 Java 基础镜像变体(例如需要某个 JDK 实现而不是默认发行版);
- 需要安装不通用、且会显著增大镜像体积的额外系统包(如 GPU/OpenCL 运行时、特定编解码库)。
在动手之前,应优先确认所需的 Java 版本与变体是否已经被官方镜像提供——这一点可以参考 docs/versions/java.md,或查阅仓库中的 images.json。从 images.json 的标签清单看,当前提供的 Java 基础覆盖非常全:
| 标签前缀 | Java | 基础发行版 | JVM | 典型架构 |
|---|---|---|---|---|
latest/stable/java25 | 25 | Ubuntu | HotSpot | amd64、arm64、riscv64 |
java25-alpine | 25 | Alpine | HotSpot | amd64、arm64 |
java25-graalvm | 25 | Oracle Linux | GraalVM | amd64、arm64(已标记 deprecated) |
java21/java21-alpine/java21-jdk | 21 | Ubuntu / Alpine | HotSpot | amd64、arm64 |
java17/java17-graalvm | 17 | Ubuntu / Oracle Linux | HotSpot / GraalVM | amd64、arm64 |
java11/java8/java16 | 11/8/16 | Ubuntu | HotSpot | amd64、arm64、armv7 |
也就是说,只有当目标 Java 运行时不在这张表里(或需要某个特定发行版 + JVM 的组合)时,才值得走下面的构建流程。
方案一:用 Compose 内联 Dockerfile 简单扩展基础镜像
如果只是想往现有镜像里加几个系统包,最简单的方式是在docker-compose.yml里使用dockerfile_inline,完全不需要改动仓库文件:
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关键点说明:
FROM itzg/minecraft-server:latest以官方发布的镜像为基底,RUN之后追加的层就是你要注入的扩展内容(本例安装webp处理工具并清理 APT 缓存以控制体积);pull: true保证每次构建都拉取最新的基底镜像,避免基于过时的本地缓存构建;pull_policy: build表示该服务在需要时执行本地构建;- 基础镜像中所有环境变量与启动流程完全保留——从 Dockerfile 可见,
ENTRYPOINT固定为/image/scripts/start,追加系统包不会影响它;Dockerfile 中的ENV TYPE=VANILLA VERSION=LATEST EULA="" ...默认值也照常生效。
进阶示例:为 C2ME 添加 Nvidia GPU(OpenCL)支持
文档给出的完整实战案例,是通过内联 Dockerfile 安装 OpenCL ICD 与 NVIDIA 驱动能力,让 C2ME(Chunky Modern 引擎)可以利用 GPU 计算。注意此例基底用的是固定 Java 版本标签itzg/minecraft-server:java25:
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这个例子值得逐层拆解,它示范了“镜像层 + Compose 层 + 运行时环境变量”三方协作:
- OpenCL ICD 配置:
ocl-icd-libopencl1提供 OpenCL 加载器,clinfo用于容器内验证设备可见性;写入/etc/OpenCL/vendors/nvidia.icd是让 ICD 指向 NVIDIA 的 OpenCL 实现(libnvidia-opencl.so.1); - 两个 ENV 是写给 NVIDIA 容器运行时看的:
NVIDIA_VISIBLE_DEVICES=all暴露全部 GPU,NVIDIA_DRIVER_CAPABILITIES=compute,utility,graphics,video声明容器需要的 GPU 能力集,从而决定注入哪些驱动库; deploy.resources.reservations.devices则是 Compose 侧向 NVIDIA 容器运行时请求 GPU 设备的标准写法;COPY ./mods /mods展示了内联 Dockerfile 也可以把构建上下文里的文件打进镜像——配合MODRINTH_PROJECTS中的c2me(Modrinth 自动下载),即可组成 C2ME + GPU 的服务端。
方案二:本地构建时使用其他 Java 基础镜像(BASE_IMAGE)
如果确实需要换掉 Java 基础镜像,Dockerfile第一行就为此留了构建参数:
- Dockerfile:
ARG BASE_IMAGE=eclipse-temurin:25-jre紧跟FROM ${BASE_IMAGE},默认基底是 Temurin 25 JRE; - 通过
docker build --build-arg BASE_IMAGE=...传入任意 JDK/JRE 基础镜像即可。
官方文档给出的 GraalVM 示例:
docker build --build-arg BASE_IMAGE=ghcr.io/graalvm/graalvm-ce:ol8-java11 -t IMG_PREFIX/minecraft-server:java11-graalvm .其中IMG_PREFIX替换为你的镜像仓库前缀(如组织名或私有 registry 地址)。这里选择 GraalVM 11 作为基底时,构建产物标签命名为java11-graalvm也与官方标签体系(见 images.json 中java17-graalvm等命名惯例)保持一致。
注意基底与安装脚本的匹配关系。构建过程中,Dockerfile 通过 BuildKit 的--mount=source=build挂载仓库的build/目录并执行:
TARGET=${TARGETARCH}${TARGETVARIANT} /build/run.sh install-packages而 build/run.sh 的实现是通过读取镜像内/etc/os-release的ID=字段来分发到对应发行版脚本的:
distro=$(cat /etc/os-release | grep -E "^ID=" | cut -d= -f2 | sed -e 's/"//g') "$(dirname "$0")/${distro}/$1".sh仓库目前为三种发行版各维护一份 install-packages.sh(ubuntu/alpine/ol,分别对应 Ubuntu、Alpine、Oracle Linux)和setup-user.sh。因此当你通过BASE_IMAGE换一个 Java 基底时,该基底的os-release ID必须是ubuntu、alpine或ol之一,否则run.sh找不到对应的安装脚本而构建失败——这从源码结构看是该方案最硬的约束。
方案三:多架构镜像构建(buildx / BuildKit)
前提:确保 Docker 已启用 buildx/BuildKit 支持(较新的 Docker Engine 默认已启用,可用docker buildx version确认)。
构建多架构并推送
docker buildx build --platform=linux/arm64 --platform=linux/arm/v7 --platform=linux/amd64 --tag IMG_PREFIX/minecraft-server --push .这条命令一次构建 arm64、arm/v7、amd64 三个目标平台的镜像,并以 manifest 形式推送到IMG_PREFIX/minecraft-server命名的仓库。Dockerfile中为此做了专门适配:Dockerfile 声明了TARGETOS、TARGETARCH、TARGETVARIANT三个全局参数,用于按平台选择对应的二进制工具链,例如 Dockerfile 中按${TARGETOS}_${TARGETARCH}${TARGETVARIANT}下载平台匹配的easy-add。
本地构建(不支持多架构)
多架构输出只支持--push;如果只想把镜像加载进本地 daemon(--load),则只能产出当前宿主架构的单架构镜像:
docker buildx build --tag IMG_PREFIX/minecraft-server --load .或者干脆用普通构建:
docker build -t IMG_PREFIX/minecraft-server .通过构建参数安装额外系统包
不构建新镜像的前提下,仓库为“往官方构建流程里加包”留了三个发行版专属的 build arg,声明在 Dockerfile:
| 构建参数 | 适用基底 | 默认值 |
|---|---|---|
EXTRA_DEB_PACKAGES | Debian/Ubuntu 系 | 空 |
EXTRA_DNF_PACKAGES | Oracle Linux(dnf)系 | 空 |
EXTRA_ALPINE_PACKAGES | Alpine 系 | 空 |
用法示例(以 Ubuntu 基底加两个包为例):
docker build --build-arg EXTRA_DEB_PACKAGES="libwebp-dev imagemagick" -t IMG_PREFIX/minecraft-server:with-webp .这三个参数是如何生效的,可以对照各发行版安装脚本看到确切机制——它们是字符串展开进包管理器命令:
- Ubuntu:build/ubuntu/install-packages.sh 在
apt-get install的包列表末尾追加${EXTRA_DEB_PACKAGES}; - Oracle Linux:build/ol/install-packages.sh 在
dnf install列表末尾追加${EXTRA_DNF_PACKAGES}; - Alpine:build/alpine/install-packages.sh 在
apk add列表末尾追加${EXTRA_ALPINE_PACKAGES}。
需要注意:脚本会按ID=自动选择对应发行版脚本,因此只有与基底匹配的那个EXTRA_*参数会生效——例如 Ubuntu 基底上设置EXTRA_ALPINE_PACKAGES不会产生任何效果。此外 Dockerfile 还有一个配套的FORCE_INSTALL_PACKAGES=1参数,用于控制是否强制执行整段包安装步骤。
构建产物内部结构速览
无论走上述哪条路径,最终镜像的装配逻辑都来自仓库根的 Dockerfile,理解它对排查自定义镜像问题很有帮助:
- Dockerfile:从
tianon/gosu复制gosu,供启动脚本以降权用户方式运行; - Dockerfile:按
TARGETOS/TARGETARCH下载easy-add、restify(Web 健康检查)、rcon-cli(RCON 命令)、mc-monitor、mc-server-runner与mc-image-helper等二进制工具,这些都是启动脚本的依赖组件; - Dockerfile:把
scripts/start*启动链、scripts/auto/守护脚本与scripts/shims/命令垫片复制到镜像,并在/usr/local/bin建立符号链接;Dockerfile 还会把 files/ 中的默认server.properties、knockd 配置等带入/image/; - Dockerfile:声明
VOLUME /data、WORKDIR /data、EXPOSE 25565,并设置TYPE=VANILLA VERSION=LATEST EULA=""等默认环境变量——因此自定义镜像运行时这些运行参数与官方镜像完全一致; - Dockerfile:
ENTRYPOINT ["/image/scripts/start"]与HEALTHCHECK ... CMD mc-health。/image/scripts/start是整个启动流程的编排入口(负责设置环境变量、下载服务器 jar、部署 modpack、启动服务器等),自定义基底镜像时不应破坏这些脚本的依赖关系。
小结
- 只加少量系统包:优先用 Compose 的
dockerfile_inline,配合pull: true保持基底新鲜,不需要维护独立 Dockerfile; - 换 Java 基础镜像:
docker build --build-arg BASE_IMAGE=...,但基底发行版必须是 ubuntu/alpine/ol 三者之一(由 build/run.sh 的分发逻辑决定); - 多架构发布:
docker buildx build --platform=... --push;本地加载用--load或普通docker build; - 构建期批量加包:
EXTRA_DEB_PACKAGES/EXTRA_DNF_PACKAGES/EXTRA_ALPINE_PACKAGES三个 build arg,各自只对匹配的基底生效。
动手前务必对照 docs/versions/java.md 与 images.json 确认现有官方标签已无法满足需求——这正是文档把该页标注为“advanced use only”的原因。
【免费下载链接】docker-minecraft-serverDocker image that provides a Minecraft Server for Java Edition that automatically installs/upgrades versions, modloaders, modpacks and more at startup项目地址: https://gitcode.com/GitHub_Trending/do/docker-minecraft-server
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考