今天研究了一下docker中运行minecraft,原因是希望在不给ssh的情况下允许别人进入服务器后台,因为已经部署了portainer,所以希望可以直接通过portainer操作后台
构建镜像
首先需要一个镜像来运行服务端
一开始我选择了Alpine作为底包,然后发现这个包实在是太干净了,甚至用的都不是glibc,下好的预编译的jdk没法跑,于是换了ubuntu
然后希望通过不同的目录来区分各个不同的子服,所以用环境变量+启动脚本动态选择工作目录
Dockerfile
# ubuntu 作为基础镜像。
FROM ubuntu:24.04
ENV TINI_VERSION=v0.19.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini
# 设置环境变量的默认值,这些值会被 docker-compose.yml 中的配置覆盖。
ENV SERVER_NAME=minecraft_server
ENV START_CMD="/java/bin/java -Xms1G -Xmx1G -jar server.jar --nogui"
# 设置容器内的通用工作目录。
WORKDIR /${SERVER_NAME}
# 暴露 Minecraft 服务器默认的 TCP 和 UDP 端口。
EXPOSE 25565
# 将启动脚本复制到镜像中。
COPY start.sh /start.sh
# 授权启动脚本可执行权限。
RUN chmod +x /start.sh
# 设置入口点。tini 确保当容器收到停止信号时,能优雅地关闭 Java 进程。
ENTRYPOINT ["/tini", "--"]
# 定义默认的启动命令。
CMD ["/start.sh"]
start.sh
#!/bin/bash
# 检查环境变量是否已设置
if [ -z "$SERVER_NAME" ]; then
echo "Error: SERVER_NAME environment variable is not set correctly."
exit 1
fi
cd /$SERVER_NAME
echo "starting..."
exec $START_CMD
# 构建指令
docker build -t minecraft-universal:1.0 .
docker compose
services:
sc:
image: minecraft-universal:1.2
container_name: sc # 容器名字
# 允许attach
stdin_open: true
tty: true
ports:
- "35565:25565" # 游戏端口映射,可以修改为其他端口
environment:
# 服务器名
SERVER_NAME: "sc"
START_CMD: "/java/bin/java -jar fabric-server-mc.1.21.8-loader.0.17.2-launcher.1.1.0.jar nogui"
volumes:
# 挂载宿主机的 Java 目录到容器中的 /java
- /usr/local/jdk/21:/java
# 挂载宿主机的服务器目录到容器中
- ./sc:/sc
restart: unless-stopped
使用如上配置之后可以在attach后正常和服务端控制台交互
重点是 stdin_open: true 和 tty: true