初次接触使用 Docker 和尝试打包 Minecraft 的踩坑记录: Play Server 的打包

2021-02-07

使用 Overlayfs 来实现程序和数据分开

Docker 的 Volume 挂载在 Container 中的效果类似于 Linux 下的 mount ,故为了做到在基础上增加一个“写层”,需要在 Container 中使用 Overlayfs 。

此方法有限制,要求 upper 层所在的文件系统不能是另外一个 Overlayfs 的 upper,且该方法需要特权。

Overlayfs 中的 whiteout

Overlayfs 中的文件类型为 c 的文件是字符文件,即 whiteout,用于标识文件删除。

该文件可以被 tar 打包。

Overlayfs 挂载后需要重新进入

使用 overlayfs 挂载完目录后,若合并后的目录与源目录相同,需要重新 cd 到目录内,否则修改的会是原有的内容。

使用 gosu 来实现低权限用户运行程序

使用低权限用户运行程序,可以降低因为给予 --cap-add SYS_ADMIN 权限导致的宿主系统被攻破的风险。

使用 gosu 可以在 shell 脚本中降低权限到一般用户后执行,Docker 中的 redis 就是这么干的。而且 gosu 更像 sudo 而非 su ,使用起来更加自然一些。

不知道 gosu 是否可以让程序避免收不到 SIGTERM 的尴尬? SIGTERM not received by java process using 'docker stop' and the official java image

拙劣的 gosu 替代品

su www-data -s '/bin/bash' -p -c 'your command here'

关于 JAVA_OPTS

JAVA_OPTS 这个环境变量,原版 Java 是不会读取的。这个环境变量是是一些热门的 Java Web 框架所拓展支持的,故自己编写启动脚本的时候,需要手动将这个添加到命令行中。

解决程序无法收到 SIGTERM 信号的问题

  1. 使用 [ "" ] entrypoint 语法
  2. 在脚本中使用 exec

sigterm 与 forged minecraft

搭配有 forge 的 Minecraft 服务器并不能很好的处理 sigterm 信号,而该信号正是 Docker 发送的结束信号,有一个小模组,叫做 sigterm-catcher 可以很好的处理这个问题,它会将 sigterm 等信号转换为 stop 指令,优雅的关闭掉服务器。

模组变更情况

更新了 forge 。从 http://files.minecraftforge.net/maven/net/minecraftforge/forge/index_1.12.2.html 下载。

更新了 spongeforge ,但是止步在了 7.2.2 ,因为 7.2.3 版本会和 appliedenergistics2 出现冲突(卡在地图生成步骤) Crash with AE2 exist

这个冲突也比较有趣,更新 sponge 到最新稳定版后,若更新 forge 到最新版,或者不更新,服务器都能正常启动,若 forge 更新到 sponge 需要的最新版后,服务器就崩溃。

https://www.spongepowered.org/downloads/spongeforge/stable/1.12.2 下载。

forge 和 spongeforge 版本应该匹配。https://docs.spongepowered.org/stable/en-GB/server/getting-started/implementations/spongeforge.html#dedicated-servers

更新了 foamfix ,因为 forge 更新了,这个不更新,会出冲突(crash)。

更新了 phosphor ,0.2.7 版本好像可以不需要手动设置 sponge 中的光照设置了,但是由于该版本放在客户端内会导致崩溃,故升级到 0.2.6 版本(还是需要手动设置光照)。

更新了 randompatches ,并且按照作者推荐增加了 randomtweaks 。

更新了 LagGoggles,同时因为其新版本好像没有 spongeforege 版本,故换成了 forge 版本,同时因为依赖关系,增加了库 TickCentral 。
为了显示卡顿情况,可能客户端也需要这个模组。

切换服务器的认证方式从离线模式启动+进入服务器后认证,变为在线模式启动+劫持mojang认证接口。
故增加了 authlib-injector 。
故移除了 flexiblelogin OfflineServerUsernameWebRequestNetworkManager 。

移除了 PrismPlus,因为其功能已经并入主线 Console SPAM

增加了 signal-catcher (server only) ,以处理 sigterm 事件。

增加了 AromaBackup (server only),以备份存档,同时因为依赖关系,增加了库 Aroma1997Core 。

Sponge 模组 AntiAttackRL EpicBanItem griefprevention LuckPerms Nucleus Prism ServerListPlus 被更新。

一个不错的 Sponge 插件清单

离线服务器安全问题

离线服务器运行时,客户端与服务器的数据包是不经过加密的,也就是说密码是在公网透明的。

(不过讲道理 mc 服务器又不需要证书,mitm 太容易了)

正版登录与离线服务器

在本地测试可以正常进入上次的存档,并且无需正版登录(即UUID并非正版(好像正版ID进入离线服务器是不使用正版UUID的)),ic2 正常工作。

游戏数据迁移

data 目录是由 aliyun-cn-beijing 20191201 快照中差分出来的,在数据导入后,为了避免重复,可以删除。

打包成 Docker 的 overlayfs 格式。

cd server-migration/
mkdir -p /tmp/data-build/data/{upper,work}
chmod a+rwx /tmp/data-build/data/upper
cp -r data/* /tmp/data-build/data/upper
chown -R 1000:1000 /tmp/data-build/data/upper/*
tar -C /tmp/data-build -cvzf data-init.tgz data
rm -r /tmp/data-build

Play Server 打包运行备份命令

# 打包
docker build -t wonld-orbis-server .

# 运行(最低要求)(只要在 server.properties 里关掉了 maxtick,cpu 使用率没有特定要求)
# or --privileged
docker run --cap-add SYS_ADMIN -dit -m 1600m --memory-swap 1600m -e JAVA_OPTS='-Xmx900m' -e 'AUTH_SERVER=https://auth.orbis.wonld.com/api/yggdrasil' -p 25565:25565 -p 25565:25565/udp -v /play-server-data/data:/data --name mc wonld-orbis-server

# 运行(推荐)(1.2 倍启动时间,相对于无限制(非常好了))(全新启动后,docker stats 显示内存使用 1.7g 如果用 swap 的话,堆大小还能更大一些)
docker run --cap-add SYS_ADMIN -dit --cpus 2 -m 2g --memory-swap 2g -e JAVA_OPTS='-Xmx1200m' -e 'AUTH_SERVER=https://auth.orbis.wonld.com/api/yggdrasil' -p 25565:25565 -p 25565:25565/udp -v /play-server-data/data:/data --name mc wonld-orbis-server

# 启动和停止
docker stop yd
docker start yd

# 进入控制台(Ctrl-P Ctrl-Q to detach)
docker attach yd

# 服务器内有备份mod

部署到服务器

# 请先完成 auth server 的配置

# local
docker build -t wonld-orbis-server .
docker save wonld-orbis-server | gzip > image.tgz

# remote
mkdir -p /sharedfolders/A/Docker/wonld-orbis-server
chown -R 1000:1000 /sharedfolders/A/Docker/wonld-orbis-server
pushd /sharedfolders/A/Docker/wonld-orbis-server
# copy local:image.tgz data-init.tgz -> remote wonld-orbis-server/
tar xzvf data-init.tgz
docker load < image.tgz
# 使用了 swap 以尽可能的使用内存
docker run --cap-add SYS_ADMIN -dit --cpus 2 -m 2g --memory-swap 4g -e JAVA_OPTS='-Xmx1500m' -e 'AUTH_SERVER=http://192.168.29.3/api/yggdrasil' --network wonld-orbis-net --ip 192.168.29.2 -p 25565:25565 -p 25565:25565/udp -v /sharedfolders/A/Docker/wonld-orbis-server/data:/data --name mc wonld-orbis-server

配置

启用了 online mode :

server.properties:
online-mode=false => true

关闭了版本检查:

config/forge.cfg:
general.disableVersionCheck=false => true
version_checking.Global=true => false

config/AppliedEnergistics2/VersionChecker.cfg:
general.enabled=true => false

阿里云转发

每次重启系统后需要手动运行一次。

#!/bin/bash

echo 1 > /proc/sys/net/ipv4/ip_forward

iptables -t nat -A PREROUTING -p tcp --dport 25565 -j DNAT --to 192.168.3.1:25565
iptables -t nat -A POSTROUTING -d 192.168.3.1 -p tcp --dport 25565 -j MASQUERADE

iptables -t nat -A PREROUTING -p udp --dport 25565 -j DNAT --to 192.168.3.1:25565
iptables -t nat -A POSTROUTING -d 192.168.3.1 -p udp --dport 25565 -j MASQUERADE
维护网站需要一定的开销,如果您认可这篇文章,烦请关闭广告屏蔽器浏览一下广告,谢谢!
加载中...

(。・∀・)ノ゙嗨,欢迎来到 lookas 的小站!

这里是 lookas 记录一些事情的地方,可能不时会有 lookas 的一些神奇的脑洞或是一些不靠谱的想法。

总之多来看看啦。