docker-minecraft-server 镜像构建实战:内联 Dockerfile 扩包、自定义 Java 基础镜像与多架构构建
2026/9/14 20:21:27 网站建设 项目流程

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/java2525UbuntuHotSpotamd64、arm64、riscv64
java25-alpine25AlpineHotSpotamd64、arm64
java25-graalvm25Oracle LinuxGraalVMamd64、arm64(已标记 deprecated)
java21/java21-alpine/java21-jdk21Ubuntu / AlpineHotSpotamd64、arm64
java17/java17-graalvm17Ubuntu / Oracle LinuxHotSpot / GraalVMamd64、arm64
java11/java8/java1611/8/16UbuntuHotSpotamd64、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 层 + 运行时环境变量”三方协作:

  1. OpenCL ICD 配置ocl-icd-libopencl1提供 OpenCL 加载器,clinfo用于容器内验证设备可见性;写入/etc/OpenCL/vendors/nvidia.icd是让 ICD 指向 NVIDIA 的 OpenCL 实现(libnvidia-opencl.so.1);
  2. 两个 ENV 是写给 NVIDIA 容器运行时看的NVIDIA_VISIBLE_DEVICES=all暴露全部 GPU,NVIDIA_DRIVER_CAPABILITIES=compute,utility,graphics,video声明容器需要的 GPU 能力集,从而决定注入哪些驱动库;
  3. deploy.resources.reservations.devices则是 Compose 侧向 NVIDIA 容器运行时请求 GPU 设备的标准写法;
  4. 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-releaseID=字段来分发到对应发行版脚本的:

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必须是ubuntualpineol之一,否则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 声明了TARGETOSTARGETARCHTARGETVARIANT三个全局参数,用于按平台选择对应的二进制工具链,例如 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_PACKAGESDebian/Ubuntu 系
EXTRA_DNF_PACKAGESOracle Linux(dnf)系
EXTRA_ALPINE_PACKAGESAlpine 系

用法示例(以 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-addrestify(Web 健康检查)、rcon-cli(RCON 命令)、mc-monitormc-server-runnermc-image-helper等二进制工具,这些都是启动脚本的依赖组件;
  • Dockerfile:把scripts/start*启动链、scripts/auto/守护脚本与scripts/shims/命令垫片复制到镜像,并在/usr/local/bin建立符号链接;Dockerfile 还会把 files/ 中的默认server.properties、knockd 配置等带入/image/
  • Dockerfile:声明VOLUME /dataWORKDIR /dataEXPOSE 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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询