1. 为什么用 Docker 跑 WOW 服务端是个靠谱选择把 WOW 服务端塞进 Docker 里跑这件事在几年前还属于折腾党专属现在已经成了不少私服维护者和单机怀旧玩家的常规操作。核心原因很简单WOW 服务端无论是 TrinityCore、AzerothCore 还是 CMaNGOS 这类开源项目的依赖链条特别长MySQL、Boost、OpenSSL、CMake、GCC 版本一个不对就编译报错换台机器重来一遍能折腾一整天。Docker 把这些依赖全部封进镜像一次构建到处运行省掉的就是这部分重复劳动。这篇文章面向三类人一是想在自己电脑或小主机上搭个单机 WOW 服务端自己玩的玩家二是需要频繁重建测试环境、做插件或数据库调试的开发者三是手里有台闲置 Linux 机器想跑个稳定服务端长期挂着的运维爱好者。不管你之前有没有 Docker 基础只要跟着走一遍都能把服务端跑起来。先说清楚一个前提WOW 服务端本身是计算密集 内存敏感型应用。worldserver 进程启动后加载地图、VMaps、MMaps内存占用轻松上 2GB 到 4GB玩家多了还会涨。所以 Docker 部署不是随便找台机器就行宿主机的内存和 CPU 才是真正的瓶颈容器只是把环境标准化了而已。这一点想明白后面选镜像、配资源限制的时候就不会踩坑。另外要区分清楚Docker 解决的是环境一致性问题不解决性能问题。很多人以为上了 Docker 就万事大吉结果发现 worldserver 启动慢、卡顿回头一查是宿主机内存不够或者磁盘是机械盘。所以本文除了讲怎么搭还会重点讲资源怎么分配、数据怎么持久化、网络怎么配这些才是真正决定你能不能长期稳定跑下去的关键。2. 镜像选型官方镜像、社区镜像还是自己构建2.1 三种镜像来源的实际差异搭 WOW 服务端第一步就是决定用哪个镜像。市面上的选择大致分三类我把它拉成表格对比一下方便你按自己的情况选。镜像来源优点缺点适合人群社区现成镜像拉下来就能跑省去编译版本可能老旧作者不一定维护安全性未知只想快速体验的新手自己构建镜像版本可控能改源码透明首次构建耗时长需要一定编译知识开发者、长期维护者官方/项目方镜像相对规范有文档WOW 服务端项目大多不提供官方镜像少数有官方支持的项目我的建议是如果你只是想快速跑起来看看先用社区镜像试水如果打算长期用、要改配置、要装模块一定要自己构建。原因很现实——社区镜像你根本不知道里面装了什么数据库密码是不是默认的端口有没有多余暴露出了问题也没法排查。自己构建虽然第一次要等编译但后面所有东西都在你掌控里。2.2 自己构建镜像的核心思路自己构建不等于从零写 Dockerfile。主流开源服务端项目比如 AzerothCore本身就提供了 Docker 支持仓库里通常有docker-compose.yml和对应的 Dockerfile。你要做的是理解它的分层逻辑而不是重写。典型的构建分两层基础层装编译工具链和依赖库build-essential、cmake、libboost、libssl、libmysqlclient 等这一层变化少可以缓存复用。应用层拷贝源码、编译、生成可执行文件这一层每次改代码都要重建。# 基础层示例简化版实际以项目仓库为准 FROM ubuntu:22.04 AS builder RUN apt-get update apt-get install -y \ build-essential cmake git \ libboost-all-dev libssl-dev \ libmysqlclient-dev libreadline-dev \ rm -rf /var/lib/apt/lists/*这里有个经验点编译阶段和运行阶段要分开。编译需要一大堆开发库运行只需要运行时库。用多阶段构建multi-stage build能把最终镜像从几个 GB 压到几百 MB传输和启动都快很多。很多人图省事把编译工具全留在运行镜像里结果镜像臃肿得离谱完全没必要。2.3 版本对齐这件事比想象中重要WOW 服务端对数据库 schema 版本、客户端版本、DBC 文件版本是强绑定的。你用的服务端核心是 3.3.5a 分支客户端就必须是 3.3.5a数据库 schema 也要对应。Docker 镜像里如果打包了固定版本的 schema你换了客户端版本就会连不上或者数据错乱。所以选镜像或构建镜像时一定要确认它对应的游戏版本并且把版本号写进镜像 tag 里比如my-wow-server:3.3.5a-v1。别用latest哪天镜像更新了版本对不上你会排查到怀疑人生。这是我在实际维护中踩过的最典型的坑之一。3. 用 docker-compose 编排数据库与服务端3.1 为什么强烈建议用 compose 而不是 docker run单跑一个容器用docker run没问题但 WOW 服务端至少涉及两个组件数据库MySQL/MariaDB和服务端进程authserver worldserver。它们之间有启动顺序依赖——数据库没起来worldserver 连不上就会退出。用docker run你得手动控制顺序、手动建网络、手动挂卷命令长到没法维护。docker-compose把这些声明式地写在一个 YAML 里一条docker compose up -d全搞定还能用depends_on加健康检查控制启动顺序。这是长期维护的正确姿势。3.2 一份可参考的 compose 结构services: wow-db: image: mysql:8.0 container_name: wow-db environment: MYSQL_ROOT_PASSWORD: your_strong_password MYSQL_DATABASE: world volumes: - ./data/mysql:/var/lib/mysql - ./sql/init:/docker-entrypoint-initdb.d command: --default-authentication-pluginmysql_native_password healthcheck: test: [CMD, mysqladmin, ping, -h, localhost] interval: 10s timeout: 5s retries: 10 wow-server: image: my-wow-server:3.3.5a-v1 container_name: wow-server depends_on: wow-db: condition: service_healthy volumes: - ./data/server:/opt/wow/data - ./etc:/opt/wow/etc ports: - 3724:3724 # authserver - 8085:8085 # worldserver restart: unless-stopped几个关键点解释一下。healthcheck那段是必须的因为 MySQL 容器启动完成和能接受连接是两回事光靠depends_on不加健康检查worldserver 大概率会在数据库还没 ready 的时候启动然后崩掉。mysql_native_password这个参数是因为部分老版本服务端的数据库驱动对新版 MySQL 的默认认证方式支持不好加上它兼容性更稳。3.3 数据持久化别把角色数据弄丢了容器是用完即弃的删了容器里面的数据就没了。WOW 服务端有两类数据必须持久化到宿主机数据库数据角色、账号、物品、任务进度全在这里丢了等于白玩。服务端配置和日志worldserver.conf、authserver.conf、日志文件改一次不容易。上面 compose 里用volumes把./data/mysql挂到容器的/var/lib/mysql这就是持久化的关键。一定要用 bind mount宿主机目录而不是匿名 volume因为匿名 volume 你根本找不到在哪备份和迁移都麻烦。用宿主机目录直接tar打包就能备份换机器拷贝过去就能恢复。提示数据库目录的权限要提前处理好。MySQL 容器里跑的是 mysql 用户UID 通常 999宿主机目录如果权限不对容器会启动失败并报权限错误。可以先chown -R 999:999 ./data/mysql再启动。4. 网络配置与端口映射的坑4.1 容器网络不通的常见原因docker 网络不通是搜索量极高的问题在 WOW 服务端场景里尤其常见。典型表现是worldserver 起来了但客户端连不上或者 authserver 能连、worldserver 连不上。根本原因通常是服务端配置里写的地址和客户端实际访问的地址不一致。WOW 服务端有两个配置文件里面的地址字段要填对authserver.conf里的LoginDatabaseInfo指向数据库地址。worldserver.conf里的WorldDatabaseInfo、CharacterDatabaseInfo指向数据库地址。还有BindIP和对外广播的地址。在 Docker 环境里容器之间通信用服务名比如wow-db客户端访问用宿主机 IP。这两个地址不能混。很多人把数据库地址写成127.0.0.1在容器里这个地址指向容器自己当然连不上数据库。正确写法是wow-dbcompose 里的服务名。4.2 端口映射与防火墙WOW 服务端默认用两个端口3724authserver和8085worldserver。compose 里映射到宿主机后客户端连的是宿主机 IP 加这两个端口。如果客户端连不上按这个顺序排查容器是否在运行docker compose ps端口是否监听ss -tlnp | grep -E 3724|8085宿主机防火墙是否放行ufw status或firewall-cmd --list-ports从容器内部测试数据库连通性docker exec -it wow-server ping wow-db我遇到过最隐蔽的一次是宿主机开了防火墙但只放行了 37248085 没放结果登录能过、进游戏卡在角色列表。这种问题不看端口监听状态根本想不到。4.3 自定义网络让容器互相发现compose 默认会创建一个 bridge 网络服务之间可以用服务名互相解析。但如果你手动docker run或者跨 compose 文件就要自己建网络docker network create wow-net docker run --network wow-net --name wow-db ... docker run --network wow-net --name wow-server ...同一个网络里的容器才能用名字互相访问。这是docker 网络不通问题里最基础也最容易被忽略的一点——两个容器不在同一个网络怎么配都连不上。5. 资源限制、性能调优与常见启动失败5.1 给容器设资源上限别让它拖垮宿主机WOW 服务端吃内存如果不限制worldserver 可能把宿主机内存吃光导致整机卡死。compose 里可以加资源限制wow-server: deploy: resources: limits: cpus: 2.0 memory: 4G reservations: memory: 2Glimits是硬上限reservations是保证分配。给 worldserver 留 4G 上限比较稳妥单机玩 2G 也够但地图全开、玩家多的时候会紧张。CPU 给 2 核基本够用编译阶段可以临时放开。5.2 启动失败的几类典型原因第一类虚拟化支持问题。在 Windows 上装 Docker Desktop如果 BIOS 里没开虚拟化会直接报 virtualisation support wasnt detected 之类的错误Docker Desktop 根本起不来。这个跟 WOW 无关是 Docker 本身的前置条件去 BIOS 打开 VT-x/AMD-V 即可。第二类数据库连接失败。worldserver 启动日志里出现 Cant connect to MySQL server八成是数据库地址、端口、密码、schema 版本对不上。逐个核对worldserver.conf里的连接串。第三类数据文件缺失。服务端需要 DBC、地图、VMaps、MMaps 这些提取出来的数据文件。这些文件通常不打包进镜像太大要单独挂载。缺了会报 Unable to load map 之类的错误。挂载路径要和配置里的DataDir一致。第四类权限错误。容器内进程没有权限写日志或数据目录报 Permission denied。解决办法是调整宿主机挂载目录的属主或者让容器以正确用户运行。5.3 镜像下载慢的应对国内拉 Docker Hub 镜像慢是常态。可以配置镜像加速器在 Docker Desktop 设置里或/etc/docker/daemon.json里配registry-mirrors。但要注意加速器只对 Docker Hub 官方镜像有效你自己构建的镜像或者第三方仓库的镜像不一定走加速。如果实在慢可以考虑把基础镜像先docker pull下来构建时就能命中缓存。6. 日常维护备份、更新与日志排查6.1 数据库备份的正确姿势角色数据是命根子定期备份不能省。最直接的方式是mysqldumpdocker exec wow-db mysqldump -uroot -pyour_password \ --databases auth world characters \ backup_$(date %Y%m%d).sql把 auth、world、characters 三个库都导出来。恢复的时候反过来mysql backup.sql即可。建议写个 cron 每天跑一次保留最近 7 天。别嫌麻烦角色数据丢了是真的找不回来。6.2 更新服务端的流程更新分两种情况。只改配置改完etc目录下的 conf 文件docker compose restart wow-server就行。更新服务端程序重新构建镜像然后docker compose up -d --buildcompose 会用新镜像重建容器数据卷不受影响。这里有个顺序问题如果新版本服务端需要数据库 schema 升级要先停服务端、升级数据库、再启动新服务端。顺序错了可能数据损坏。升级前务必备份。6.3 看日志定位问题排查问题第一件事就是看日志docker compose logs -f wow-server docker compose logs -f wow-db-f是持续跟踪。worldserver 的启动日志会明确告诉你卡在哪一步——是数据库连接、数据文件加载还是端口绑定。养成看日志的习惯比到处搜docker 网络不通高效得多。7. 我在实际部署中总结的几条经验搭过几轮之后有几个体会值得单独说。第一别追求一步到位。先把数据库和服务端跑起来能登录进游戏再去调性能、加模块。一上来就想配最优往往卡在某个细节上出不来。第二配置文件用挂载而不是打进镜像。配置改了不用重建镜像直接重启容器效率差好几倍。第三给容器起明确的名字wow-db、wow-server比一串随机 ID 好管理太多排查问题时一眼就能对上。第四宿主机磁盘尽量用 SSDworldserver 启动要读大量地图数据机械盘能让你等到怀疑人生。最后分享一个小技巧如果你只是单机自己玩其实可以把 authserver 和 worldserver 放在同一个容器里用 supervisor 管理省一个容器的开销。但如果是多人或者要长期维护还是拆开更清晰出问题好定位。这个取舍看你自己的场景没有绝对的对错。