如何把 Docker 游戏服务器真正做成可迁移备份:DST 与 Palworld 实战

Docker 游戏服务器看起来很好迁移:保存镜像、复制配置和存档,再到另一台机器上重新启动容器即可。 真正实践之后会发现,事情远没有这么简单。 一个真正合格的迁移包,需要回答的并不是: 文件有没有备份? 而是: 如果原服务器彻底不存在,只剩下这个备份包,能不能在另一台 Linux + Docker 主机上重新启动服务器,并继续读取原来的世界和存档? 这两者之间存在很大差别。 本文以 Don’t Starve Together(DST) 和 Palworld 两套 Docker 游戏服务器为例,介绍一套相对可靠的 Docker 游戏服务器迁移方法。 所有涉及实际服务器路径、用户名、端口、域名、镜像摘要、世界 ID、时间戳等信息均已脱敏。 一、首先明确什么叫“可迁移备份” 普通备份可能只包含: 这样的备份当然有价值,但还不能证明它可以恢复。 完整迁移至少涉及四个部分: 进一步说,一个理想的迁移包应该具备: 其中最关键的是: 不能依赖原服务器上仍然存在的东西。 例如,如果恢复过程中仍然需要: 那么这并不是严格意义上的自包含迁移。 因为几年之后: 因此,Docker image 本身也应该成为备份的一部分。 二、先搞清楚数据到底在哪里 Docker 应用的数据并不一定存储在 Docker volume 中。 实际部署中常见三种情况。 1. Named Volume 例如: 这种情况下,需要单独备份 …

Docker Jitsi 升级实录:Rootless 架构、TLS、XMPP 与稳定迁移

Jitsi Meet 的 Docker 升级,有时并不是简单修改镜像标签。 当新版本从传统 rootful 容器转向: 部署模型本身就发生了改变。 如果仍然拿旧 Compose 文件直接套新镜像,很容易遇到: 下面整理一次完整迁移过程中最值得记录的技术问题。 一、为什么不能只替换 image tag 旧版 Jitsi Docker 架构通常允许容器: 新版架构则变成: 同时容器切换为非 root 用户运行,并且: 这意味着旧部署中很多“碰巧能工作”的做法都会失效。 例如旧私钥: 以前 root 容器当然可以读取。 切换到 rootless 后: 文件明明存在,应用却等同于“没有这个文件”。 二、Web 服务为什么会因为一把私钥直接失效 Jitsi Web 内部 Nginx 需要一对: 新版容器使用的逻辑大致是: 启动时: 问题就在“可读取”。 如果: rootless 进程只能看到证书,看不到私钥。 结果可能形成一种很特殊的状态: 然后 Nginx 启动时报错: …

Docker 化 OnlyOffice 升级实录:持久化、JWT 与容器重建的关键问题

在自托管环境中,OnlyOffice DocumentServer 往往只是一个“应用执行层”:真正需要长期保存的文档通常位于外部云盘或文件服务中,而 DocumentServer 负责文档解析、协同编辑和格式转换。 这类应用看似可以直接“拉取新镜像然后重建”,但实际升级中仍有几个很容易被忽略的问题:JWT 密钥是否稳定、容器内部数据库如何迁移、哪些目录需要持久化,以及为什么一次普通的容器重建可能突然造成明显的磁盘 I/O 压力。 下面以一次实际的 Docker 升级过程为例,整理这些问题背后的原理。 一、先区分“应用数据”和“用户数据” OnlyOffice DocumentServer 本身并不一定保存最终用户文档。 典型部署结构是: 真正重要的数据通常仍由云盘系统负责保存。 因此,对 DocumentServer 的升级策略不一定需要达到数据库服务器那种“任何字节都不能丢”的灾难恢复级别。 真正需要重点保护的是: 这也是判断备份范围时非常重要的原则: 不要因为应用内部存在数据库,就自动把它当作业务数据数据库。 二、JWT 密钥为什么应该固定 OnlyOffice 与外部云盘集成时,常使用 JWT 对请求进行认证。 一个常见问题是: 这种部署在日常运行时可能完全正常,因为普通的: 不会删除容器 writable layer。 但只要执行: 问题就暴露出来了。 更合理的做法,是把 JWT 参数放入宿主机持久化配置,例如: 再由 Compose 注入容器。 这样就形成: 以后即使: JWT 都不会因为容器生命周期变化而改变。 对于应用容器而言,这种配置持久化往往比备份整个 writable layer …