前言
6 月底的时候,我想在家里的 Linux 服务器上用 Podman 搭一个泰拉瑞亚(Terraria)服务器。因为家里已经配好了 WireGuard,平时连内网的 NAS 和其他服务都很顺畅,我本来以为跑个游戏容器也就是一行命令的事。
结果容器跑起来之后,客户端怎么都连不上。我一开始怀疑是防火墙没放行端口、rootless 容器权限不对,或者是 VPN 路由有问题,折腾了一圈才发现服务端压根就没启动成功——而罪魁祸首居然是我把世界存档的文件名拼错了。
重要
问题原因
- 启动容器时顺手同时加了
-d(后台运行)和--rm(退出即销毁),导致容器一报错退出就自动消失,连日志都看不了。- 环境变量里写的世界文件名是
6-26-vanilla.wld,但本地目录里的文件名实际上被我手误打成了6-26-vaillan.wld。
容器启动配置
我用的镜像是 ryansheehan/terraria 打包的 TShock 服务端:
docker.io/ryshe/terraria:tshock-1.4.5.6-6.1.0虽然我给容器起了个名字叫 terraria-vanilla,但实际上跑的是带插件管理的 TShock。当时配的几个主要参数如下:
- 宿主机存档目录:
/data/containers/penry/terraria-vanilla/Terraria/Worlds - 容器内挂载路径:
/root/.local/share/Terraria/Worlds - 指定加载的世界:
WORLD_FILENAME=6-26-vanilla.wld - 映射端口:
7777
前台运行与日志排查
最开始启动容器的时候,我习惯性地加上了 -d 和 --rm。
平时跑测试容器用 --rm 很方便,用完自动清理,但放在后台服务上就是个坑:如果容器里的程序一启动就崩了,--rm 会立刻把退出的容器删掉。等你发现游戏连不上、切回终端敲 podman ps -a 或者 podman logs 的时候,什么都查不到。
所以排查的第一步很简单:先把旧服务停掉,去掉 -d 和 --rm,直接在前台跑一次看看它到底卡在哪。
如果之前已经交给 systemd 管了,先停掉服务免得占着端口:
systemctl --user stop terraria-vanilla.service定位存档加载错误
改用前台交互模式启动容器后,终端马上吐出了三行输出,然后就退出了:
world_file_name=6-26-vanilla.wld
Environment WORLD_FILENAME specified
Unable to locate /root/.local/share/Terraria/Worlds/6-26-vanilla.wld看到 Unable to locate 就破案一大半了:根本不是网络或者防火墙的问题,而是容器在 /root/.local/share/Terraria/Worlds/ 里没找到 6-26-vanilla.wld 这个存档,直接退出了。
我去宿主机对应的目录看了一眼:
ls -lh /data/containers/penry/terraria-vanilla/Terraria/Worlds结果列出来的文件名是这样的:
6-26-vaillan.wld
6-26-vaillan.wld.bak
6-26-vaillan.wld.bak2对比一下才发现自己有多迷糊:
- 环境变量写的:
6-26-vanilla.wld - 实际存档名字:
6-26-vaillan.wld
建存档的时候手滑把 vanilla 打成了 vaillan,写容器启动参数的时候又按正确的单词去写,难怪服务端死活找不到文件。
提示
提示 遇到“找不到存档”报错时,如果手里本来就有存档文件,千万不要急着加自动新建世界的参数,先看一眼路径和文件名对不对,免得新建出来的空世界把人搞晕。
修正参数与测试运行
既然存档本身好端端地在目录里,就不用动文件了,直接把环境变量里的文件名改成 6-26-vaillan.wld 在前台试跑一次(泰拉瑞亚联机走的是 TCP 7777 端口):
podman run -it \
--name terraria-debug \
--publish 7777:7777/tcp \
--volume /data/containers/penry/terraria-vanilla/Terraria/Worlds:/root/.local/share/Terraria/Worlds:Z \
--env WORLD_FILENAME=6-26-vaillan.wld \
docker.io/ryshe/terraria:tshock-1.4.5.6-6.1.0只要不加 --rm,就算容器中途退出,也可以随时用下面的命令翻看日志和退出状态:
podman logs --tail=100 terraria-debug
podman inspect terraria-debug --format '{{json .State}}'配置 Quadlet 服务
前台确认能正常读到存档后,把临时测试的 terraria-debug 容器删掉,再把配置写进 ~/.config/containers/systemd/terraria-vanilla.container:
[Unit]
Description=Terraria TShock server
[Container]
ContainerName=terraria-vanilla
Image=docker.io/ryshe/terraria:tshock-1.4.5.6-6.1.0
PublishPort=7777:7777/tcp
Volume=/data/containers/penry/terraria-vanilla/Terraria/Worlds:/root/.local/share/Terraria/Worlds:Z
Environment=WORLD_FILENAME=6-26-vaillan.wld
[Service]
Restart=on-failure
TimeoutStartSec=900
[Install]
WantedBy=default.target重载 systemd 并启动服务:
systemctl --user daemon-reload
systemctl --user start terraria-vanilla.service
journalctl --user -u terraria-vanilla.service -f说明
关于数据持久化 上面的配置只挂载了
Worlds地图目录。如果平时在 TShock 里装了插件、改了权限配置,建议对照镜像文档把 TShock 的配置和插件目录也一并挂载出来,升级镜像前记得先备份好.wld存档文件。
端口与连通性检查
如果日志里已经提示世界加载完成、正在监听 7777 端口,但游戏里还是进不去,可以按顺序测一下网络:
-
在服务器上确认端口已经监听:
ss -lntp -
在连着 VPN 的电脑上测一下 7777 端口通不通:
macOS / Linux:
nc -vz 服务器VPN地址 7777Windows PowerShell:
Test-NetConnection 服务器VPN地址 -Port 7777
如果端口是通的但还是进不去游戏,一般再去核对客户端和服务端的小版本号是否一致,或者看一眼 TShock 控制台有没有报版本不匹配、密码错误之类的提示就可以了。