2274 字
11 分钟
使用Docker搭建Minecraft服务器
本文主要内容本文主要介绍如何使用Docker搭建MCSManager并开一个自己Minecraft服务器,涵盖了基础设置、数据持久化、网络配置以及Build一个自己的Minecraft服务器镜像等内容。
最后一次玩MC是在初二吧,记得当时还是1.4左右版本,记得当时玩的服务器好像叫什么秋月之光,应该在当时算大型服务器了吧,当年辛辛苦苦得到了一个信标,被人家偷走了,因此还砸坏了电脑,然后被打了一顿😂。
最近闲来无事,心血来潮,想搭建一个公益Minecraft养老生存服务器(其实是想废物利用下没用上的服务器),但是由于以前也没开过MC服务器,不知道要装什么插件,索性就放弃了。相较于开服,我还是更喜欢当个玩家(如果你看到这篇文章,愿意当服主的话,请联系我!!此消息永久有效)。此文只是记录一下使用Docker搭建Minecraft服务器的过程,方便以后回顾。
组件说明
- Docker:容器化平台。
- MCSManager:Minecraft服务器管理面板,支持多种Minecraft服务器类型。
- Minecraft服务器镜像:本文使用GitHub Action打包一个自己的服务器镜像(可以自行增加常用插件在内)
部署流程
部署MCSManager
- 创建
docker-compose.yaml文件:Terminal window mkdir -p ~/docker_data/mcsm && cd ~/docker_data/mcsm && nano docker-compose.yamldocker-compose.yaml services:web:image: githubyumao/mcsmanager-web:latestports:- 65004:23333 # 注意修改为自己的端口号volumes:- /etc/localtime:/etc/localtime:ro- ./web/data:/opt/mcsmanager/web/data- ./web/logs:/opt/mcsmanager/web/logsnetwork_mode: bridgerestart: unless-stoppeddaemon:image: githubyumao/mcsmanager-daemon:latestrestart: unless-stoppedports:- 65005:24444 # 注意修改为自己的端口号- 65008:25565 # 注意修改为自己的端口号environment:- MCSM_DOCKER_WORKSPACE_PATH=/home/ubuntu/docker_data/mcsm/daemon/data/InstanceDatavolumes:- /etc/localtime:/etc/localtime:ro- ./daemon/data:/opt/mcsmanager/daemon/data- ./daemon/logs:/opt/mcsmanager/daemon/logs- /var/run/docker.sock:/var/run/docker.socknetwork_mode: bridge - 查看生成的daemon节点key,后续需要填入MCSManager面板中:
Terminal window cat daemon/data/Config/global.json{"version": 2,"ip": "","port": 24444,"prefix": "","key": "xxxxxxx","maxFileTask": 2,"maxZipFileSize": 200,"language": "zh_cn","defaultInstancePath": "","allocatablePortRange": [10010,65500],"currentAllocatablePort": 10095,"portAssignInterval": 5,"uploadSpeedRate": 0,"downloadSpeedRate": 0} - 启动MCSManager服务
Terminal window docker compose up -d - 访问MCSManager面板,地址为
http://你的服务器IP:65004,按照web流程配置账户信息,然后进行Nginx反代(我反正添加本地节点有点问题,反代过后添加节点没问题) - 按照如下图片配置Nginx Proxy Manager反代
- 前往
AdvancedTab下的Custom Nginx Configuration,添加以下代码:
include /data/nginx/custom/cloudflare_ips.conf;# 传输时默认开启gzip压缩gzip on;# 传输时会被压缩的类型(应当依据文件压缩效果添加)gzip_types text/plain text/css application/javascript application/xml application/json;# 反向代理时,启用压缩gzip_proxied any;# 传输时压缩等级,等级越高压缩消耗CPU越多,最高9级,通常5级就够了gzip_comp_level 5;# 传输时大小达到1k才压缩,压缩小内容无意义gzip_min_length 1k;# 最大文件上传大小限制。设置0为不限制client_max_body_size 0;# 关闭缓存proxy_request_buffering off;proxy_buffering off; - 前往
- 前往面板,按图添加节点

使用Github Action构建Minecraft服务器镜像
这里以purpur端为例,其他端也可以参考类似的思路进行构建。需要什么插件可以自己加进去 我最终是推送到我自建的
gitea,如果你要推送到ghcr,直接让AI改一下这个文件即可
- 随便开个空仓库,开启Action
- 创建
purpur/Dockerfile文件Terminal window mkdir purpur && nano purpur/Dockerfilepurpur/Dockerfile ARG BASE_IMAGE=container-registry.oracle.com/graalvm/jdk:17# 使用变量作为基础镜像FROM ${BASE_IMAGE}# 定义构建参数,可以从 build-push-action 传入ARG MC_VERSION=1.20.4ARG PURPUR_JAR_NAME=purpur.jar# 安装 curl 用于下载,并清理缓存RUN microdnf install curl && \microdnf clean all# 下载 Purpur 服务端RUN curl -L -o /app/${PURPUR_JAR_NAME} \"https://api.purpurmc.org/v2/purpur/${MC_VERSION}/latest/download"# 复制启动脚本到镜像中COPY start.sh /app/start.sh# 给予启动脚本执行权限RUN chmod +x /app/start.shWORKDIR /workspace# 声明服务器数据卷,用于持久化世界、插件等数据VOLUME /workspace# 暴露 Minecraft 服务器端口EXPOSE 25565# 设置容器启动时执行的命令CMD ["/app/start.sh"] - 创建
purpur/start.sh启动脚本Terminal window nano purpur/start.shpurpur/start.sh #!/bin/sh# 自动同意 Minecraft EULAecho "eula=true" > eula.txt# 设置默认内存,如果环境变量 MEMORY 未设置,则使用 4GMEMORY=${MEMORY:-4G}# 使用 Aikar's Flags 优化启动参数# exec 会让 Java 进程替换掉 shell 进程,成为容器的主进程 (PID 1),这样可以更好地接收 Docker 的停止信号exec java -Xms${MEMORY} -Xmx${MEMORY} \-XX:+UseG1GC \-XX:+ParallelRefProcEnabled \-XX:MaxGCPauseMillis=200 \-XX:+UnlockExperimentalVMOptions \-XX:+DisableExplicitGC \-XX:+AlwaysPreTouch \-XX:G1NewSizePercent=30 \-XX:G1MaxNewSizePercent=40 \-XX:G1HeapRegionSize=8M \-XX:G1ReservePercent=20 \-XX:G1HeapWastePercent=5 \-XX:G1MixedGCCountTarget=4 \-XX:InitiatingHeapOccupancyPercent=15 \-XX:G1MixedGCLiveThresholdPercent=90 \-XX:G1RSetUpdatingPauseTimePercent=5 \-XX:SurvivorRatio=32 \-XX:+PerfDisableSharedMem \-XX:MaxTenuringThreshold=1 \-Dusing.aikars.flags=https://mcflags.emc.gs \-Daikars.new.flags=true \-jar /app/purpur.jar --nogui - 创建一个
purpur.yml文件.github/workflows/purpur.yml # .github/workflows/build-purpur.yml# ----------------------------------------------------------------# 这是一个用于构建 Minecraft Purpur 服务端 Docker 镜像的 GitHub Actions 工作流。## 功能特性:# 1. 多架构构建: 支持 amd64 和 arm64 架构。# 2. 动态 Java 版本: 自动根据输入的 Minecraft 版本选择 Java 17 或 Java 21 作为基础镜像。# - MC >= 1.20.5 使用 Java 21# - MC < 1.20.5 使用 Java 17# 3. 手动触发与版本控制: 支持手动触发并输入版本号,也支持通过 push 自动触发。# - 最终镜像标签为 <MC_VERSION>,例如 "1.20.5"。# - 各架构的中间镜像标签为 <MC_VERSION>-<arch>,例如 "1.20.5-amd64"。# 4. 串行执行: 构建任务将按顺序执行(先完成 amd64,再开始 arm64),便于排错和控制并发。# 5. 推送到私有 Gitea 仓库: 自动构建并推送到你自建的 Gitea 容器镜像仓库。# ----------------------------------------------------------------name: Build Purpur Docker Image & Push to Giteaon:# 允许在 GitHub Actions 页面手动触发workflow_dispatch:inputs:mc_version:description: 'Minecraft Version (e.g., 1.20.4, 1.20.5)'required: truedefault: '1.20.4'# 全局环境变量env:# 当 push 触发时使用的默认 Minecraft 版本DEFAULT_MC_VERSION: "1.20.4"# Gitea 上的镜像名称GITEA_IMAGE_NAME: "purpur"# 第一个需要 Java 21 的 Minecraft 版本,用于版本比较JAVA_21_CUTOFF_VERSION: "1.20.5"jobs:build-and-push-arch:strategy:fail-fast: false# 设置最大并行数为 1,实现串行执行max-parallel: 1matrix:include:- arch: amd64runner: ubuntu-latest- arch: arm64runner: ubuntu-22.04-armruns-on: ${{ matrix.runner }}permissions:contents: readpackages: writesteps:- name: Checkout repositoryuses: actions/checkout@v4- name: Determine Versionsid: get_versionsrun: |# 步骤 1: 确定 Minecraft 版本# 如果是手动触发,则使用输入的版本号;否则,使用环境变量中定义的默认版本号MC_VERSION=${{ github.event.inputs.mc_version || env.DEFAULT_MC_VERSION }}echo "MC_VERSION=$MC_VERSION" >> $GITHUB_ENVecho "Determined Minecraft version: $MC_VERSION"# 步骤 2: 根据 Minecraft 版本判断需要的 Java 版本# 使用 dpkg 工具比较版本号,这比简单的字符串比较更可靠if dpkg --compare-versions "$MC_VERSION" "ge" "${{ env.JAVA_21_CUTOFF_VERSION }}"; thenJAVA_TAG="21"echo "Version $MC_VERSION requires Java 21."elseJAVA_TAG="17"echo "Version $MC_VERSION requires Java 17."fi# 步骤 3: 设置基础镜像环境变量,供后续步骤使用BASE_IMAGE="container-registry.oracle.com/graalvm/jdk:$JAVA_TAG"echo "BASE_IMAGE=$BASE_IMAGE" >> $GITHUB_ENVecho "Using base image: $BASE_IMAGE"- name: Set up Docker Buildxuses: docker/setup-buildx-action@v3- name: Log in to Gitea Container Registryuses: docker/login-action@v3with:registry: ${{ secrets.GITEA_HOST }}username: ${{ secrets.GITEA_USERNAME }}password: ${{ secrets.GITEA_REGISTRY_PAT }}- name: Build and push Docker imageid: buildx1continue-on-error: trueuses: docker/build-push-action@v5with:context: ./purpurfile: ./purpur/Dockerfileplatforms: linux/${{ matrix.arch }}build-args: |MC_VERSION=${{ env.MC_VERSION }}# 将动态决定的基础镜像名传递给 DockerfileBASE_IMAGE=${{ env.BASE_IMAGE }}tags: ${{ secrets.GITEA_HOST }}/${{ secrets.GITEA_USERNAME }}/${{ env.GITEA_IMAGE_NAME }}:${{ env.MC_VERSION }}-${{ matrix.arch }}push: true# 禁用 provenance 和 sbom,避免创建额外的 manifestprovenance: falsesbom: falsecache-from: type=ghacache-to: type=gha,mode=max- name: Wait to retryif: steps.buildx1.outcome != 'success'run: |sleep 10- name: Build and push Docker imageif: steps.buildx1.outcome != 'success'uses: docker/build-push-action@v5with:context: ./purpurfile: ./purpur/Dockerfileplatforms: linux/${{ matrix.arch }}build-args: |MC_VERSION=${{ env.MC_VERSION }}# 将动态决定的基础镜像名传递给 DockerfileBASE_IMAGE=${{ env.BASE_IMAGE }}tags: ${{ secrets.GITEA_HOST }}/${{ secrets.GITEA_USERNAME }}/${{ env.GITEA_IMAGE_NAME }}:${{ env.MC_VERSION }}-${{ matrix.arch }}push: true# 禁用 provenance 和 sbom,避免创建额外的 manifestprovenance: falsesbom: falsecache-from: type=ghacache-to: type=gha,mode=maxmerge-manifest:needs: build-and-push-archruns-on: ubuntu-latestpermissions:contents: readpackages: writesteps:- name: Log in to Gitea Container Registryuses: docker/login-action@v3with:registry: ${{ secrets.GITEA_HOST }}username: ${{ secrets.GITEA_USERNAME }}password: ${{ secrets.GITEA_REGISTRY_PAT }}- name: Determine Minecraft Version# 在这个 job 中也需要确定版本号,以保持与上一个 job 一致run: |MC_VERSION=${{ github.event.inputs.mc_version || env.DEFAULT_MC_VERSION }}echo "MC_VERSION=$MC_VERSION" >> $GITHUB_ENV- name: Create and push manifest list with version tagrun: |IMAGE_BASE="${{ secrets.GITEA_HOST }}/${{ secrets.GITEA_USERNAME }}/${{ env.GITEA_IMAGE_NAME }}"VERSION_TAG="${IMAGE_BASE}:${{ env.MC_VERSION }}"AMD_TAG="${IMAGE_BASE}:${{ env.MC_VERSION }}-amd64"ARM_TAG="${IMAGE_BASE}:${{ env.MC_VERSION }}-arm64"echo "--- Creating Manifest List for $VERSION_TAG ---"# 清理所有可能存在的旧 manifest(忽略错误)echo "Cleaning up old manifests..."docker manifest rm ${VERSION_TAG} 2>/dev/null || truedocker manifest rm ${AMD_TAG} 2>/dev/null || truedocker manifest rm ${ARM_TAG} 2>/dev/null || true# 检查架构特定镜像状态echo "Checking image status..."docker manifest inspect ${AMD_TAG} || echo "❌ amd64 image not found or is manifest list"docker manifest inspect ${ARM_TAG} || echo "❌ arm64 image not found or is manifest list"# 检查架构镜像是否存在if docker manifest inspect ${AMD_TAG} >/dev/null 2>&1 && docker manifest inspect ${ARM_TAG} >/dev/null 2>&1; thenecho "Both architecture images exist, creating manifest list..."# 由于架构标签可能是 manifest list,我们使用 --amend 来处理docker manifest create ${VERSION_TAG} \--amend ${AMD_TAG} \--amend ${ARM_TAG}docker manifest push ${VERSION_TAG}echo "✅ Gitea manifest pushed successfully"elseecho "❌ Architecture images not ready, skipping Gitea manifest creation"fi- name: Inspect final manifestrun: |echo "--- Inspecting Final Manifest ---"docker manifest inspect ${{ secrets.GITEA_HOST }}/${{ secrets.GITEA_USERNAME }}/${{ env.GITEA_IMAGE_NAME }}:${{ env.MC_VERSION }} - 提交代码到GitHub,然后手动去触发Action构建镜像,输入你要的Minecraft版本,以下是当前支持版本(点击复制):
加载中Purpur支持版本中... - 打包完成后,前往MCSManager面板,按照图片添加一个实例:

- 运行完成后,还需要配置
端口映射以及环境变量
- 最后愉快的启动服务器吧!
使用Docker搭建Minecraft服务器
https://blog.useforall.com/posts/minecraft/minecraft-server-with-docker/ 最后更新于 2025-11-09,距今已过 7 天
部分内容可能已过时
Lim's Blog