一、写在最前面:为什么要“认真”跑一个游戏服务器

很多教程的目标只有一句话:

“服务器能跑,能进就行。”

但在真实服务器环境中,这种目标是不够的

本次实践的目标从一开始就明确为:

  • 数据必须是第一等公民
  • 容器只是可随时丢弃的运行外壳
  • 任何异常启动、重启、崩溃都不能影响世界存档
  • 即使不连接客户端,也能判断服务器是否真实可用
  • 需要时才启动,不需要时彻底停止

这不是“为了折腾”,而是为了避免后期不可控成本


二、总体设计思想

1. 核心分离原则

在本方案中,Palworld 服务被拆成三层:

层级角色处理方式
世界数据核心资产永久保存在宿主机
配置文件行为定义由管理员手动维护
容器执行外壳可随时删除

一句话总结:

世界不属于容器,容器只是世界的“临时执行环境”。


三、目录结构设计(完全脱敏)

以下为逻辑结构示意,非真实路径:

palworld-root/
├── docker-compose.yml
└── game-data/
    └── Pal/
        └── Saved/
            ├── Config/
            │   └── LinuxServer/
            │       ├── PalWorldSettings.ini
            │       └── GameUserSettings.ini
            ├── SaveGames/
            │   └── 0/
            │       └── <WORLD_ID>/
            │           ├── Level.sav
            │           ├── LevelMeta.sav
            │           └── Players/
            └── Logs/

关键点说明

  • docker-compose.yml 与数据目录同级
  • 所有世界数据、配置文件只存在于宿主机
  • 容器内部不保存任何“唯一性数据”

四、Docker Compose 的设计原则(而不是参数堆砌)

1. 镜像使用原则

  • 使用公开的 Palworld Server 镜像
  • 不绑定具体 build / manifest
  • 使用匿名方式安装服务器文件
  • 避免任何需要 Steam 账号的行为

原因很简单:

运行环境应尽量无状态、无外部依赖


2. 环境变量的克制使用

在 compose 中:

  • 只保留 UID / GID / 时区 / 基础端口
  • 不在环境变量中写入任何游戏参数
  • 所有倍率、规则、功能开关 只存在于 ini

这样做的好处是:

  • Docker 不参与“游戏逻辑”
  • ini 文件即文档,也是配置源
  • 迁移环境时不需要“回忆当初写了什么 env”

3. 禁止自动生成 / 覆盖配置

明确禁止镜像在启动时:

  • 生成默认 ini
  • 覆盖现有 ini
  • 根据 env 重写设置

这是防止世界“被重置”的关键步骤之一


五、端口策略(完全脱敏说明)

1. 对外端口原则

  • 只暴露游戏必需的 UDP 端口
  • 不暴露 REST / RCON / 查询端口
  • 不做端口扫描“猜测式配置”

示意(非真实端口):

HOST_UDP_PORT  →  CONTAINER_UDP_PORT

2. 关于“日志里出现的其他端口”

即使在 ini 中关闭了某些功能,服务端启动日志中仍可能出现:

  • “等待 REST API”
  • “检查管理接口端口”

这属于 服务端启动流程的内部逻辑,并不等价于:

  • 对外监听
  • 安全暴露
  • 网络可达

判断标准永远只有一个:

宿主机是否监听 / Docker 是否映射


六、无需客户端的可用性验证(重点)

在不连接任何游戏客户端的前提下,本次实践采用了多重独立验证

1. 容器状态验证

  • 容器处于 running
  • 健康检查通过
  • 无频繁重启

2. 网络监听验证

  • 宿主机 UDP 端口处于监听状态
  • 监听进程来自 docker-proxy
  • 未监听的端口即使存在日志提示也视为无效

3. 世界存档行为验证(最重要)

对世界主存档文件进行观测:

  • 文件存在
  • 时间戳持续更新
  • 文件大小随时间变化

示意逻辑:

时间 T1:大小 A
时间 T2:大小 B(B ≠ A)

这意味着:

  • 世界已加载
  • 自动保存机制工作
  • 服务端逻辑在持续运行

这是比“端口能连”更强的证据。


七、关于日志的正确理解

1. 不要被旧日志误导

历史 crash log、上传失败、SSL 报错等:

  • 只要不是当前运行周期生成
  • 不影响现有世界
  • 可视为“历史噪音”

2. 日志的真实用途

日志用于:

  • 判断是否启动成功
  • 判断是否进入运行态

而不是:

  • 作为“是否可玩”的唯一依据

八、为什么选择“停止并删除容器”

1. 不使用常驻服务的原因

  • 游戏服务器不是基础设施
  • 不需要 24/7 在线
  • 异常自动重启可能造成资源雪崩
  • 运维人员应明确知道什么时候服务在跑

2. 推荐的停止方式

docker compose down

效果:

  • 容器被销毁
  • 网络被清理
  • 数据完全保留

3. 停止后的验证思路

  • 无容器
  • 无端口监听
  • 无游戏进程

九、需要时的“零成本恢复”

当需要重新运行服务器:

docker compose up -d

发生的事情只有:

  • 新建容器
  • 挂载旧数据
  • 世界从原存档继续

不涉及:

  • 数据迁移
  • 恢复流程
  • 初始化风险

十、最终总结

这次实践得到的核心结论是:

  • Palworld 世界存档完全可以独立于 Docker 容器存在
  • Docker 最适合扮演“随用随起的执行层”
  • 世界是否“活着”,应通过存档写入行为判断
  • 删除容器是安全操作,只要数据在宿主机

最终状态可以概括为:

服务可用,但不强制在线;
世界存在,但不依赖容器;
资源可控,风险可回滚。

这是一个长期稳定、低风险、可复制的部署方式。

Leave a Reply

Your email address will not be published. Required fields are marked *