☰
MediaWiki+Docker企业级Wiki部署:从架构设计到运维实践
2026/10/20 8:20:44 网站建设 项目流程

要在一家公司里搞一套企业级Wiki平台,MediaWiki 基本是绕不开的选项。这个老牌开源 Wiki 引擎看着朴素,但权限体系完整、扩展插件多、内容组织能力强,特别适合做团队内部知识库。而 Docker 把 PHP 环境、数据库、依赖扩展这些最折腾人的部分直接容器化,两者配在一起,已经成为中小企业搭建内网 Wiki 的主流方式。

这篇文章把从选型、架构设计、Docker Compose 部署、缓存接入、备份恢复,再到常见问题排查的完整过程都梳理了一遍。我自己前后搭过好几套 MediaWiki,有大几百人同时在用的内网知识库,也有十几人的小团队协作站点,很多坑是实际踩过了才总结出来的。文章里写的每一步都可以直接照着做,不是那种只讲概念的泛泛之谈。

1. 为什么企业级 Wiki 要选 MediaWiki + Docker

1.1 MediaWiki 凭什么能扛起企业知识库

先说说 MediaWiki 本身。很多人一听到 MediaWiki 就想到百科类站点,觉得它界面老气,交互也跟不上现代协作工具。但企业级知识库和公开百科的需求差很多:团队需要的是稳定的权限边界、可审计的编辑记录、结构化的分类体系,以及能长期积累的开放 API。这些恰恰是 MediaWiki 的看家本领。

编辑历史完整可回溯,出了问题可以精准回滚到某个版本;分类和命名空间机制能支撑起一个多层级的知识架构,比如把公司制度、产品文档、研发规范分成不同命名空间,每个空间单独设置访问权限;用户权限系统颗粒度很细,从只读访客到管理员都有明确的角色定义。再加上 Semantic MediaWiki 这类扩展,还能给页面加上结构化属性,做成简单的数据管理平台。对一家追求长期积累的公司来说,MediaWiki 的扩展性和稳定性远比花哨的界面重要。

1.2 Docker 部署解决了哪些传统部署的硬伤

传统方式部署 MediaWiki,第一步就会劝退不少人:需要一台装了 LAMP 或 LNMP 的服务器,PHP 版本不能太老,扩展要装够,MySQL 要进行安全初始化,还得处理 PHP-FPM 和 Web 服务器的配置联动。每换一台机器就要重新来一遍,环境差异带来的诡异报错能让人排查到怀疑人生。

Docker 把这个问题解决得很干脆。官方镜像把 PHP 环境、依赖扩展、默认配置都打好了包,数据库直接用独立的容器跑,上下游依赖通过 Docker Compose 声明式管理。我实际用下来的感受是:从零开始到浏览器打开安装向导,熟练的话十分钟之内就能搞定。再往后要升级版本、迁移服务器、加一台预发布环境,靠同一套 Compose 文件就能复制出几乎一致的环境。团队协作的 Wiki 最有价值的是多年积累的内容,而不是那个安装过程本身。把环境部分做成标准化的容器编排,后续的维护成本能降一个量级。

2. 部署前必须定好的架构与版本选型

2.1 容器拆分方案:数据库和 Wiki 实例怎么组合

很多新手上来就一个 docker run 把 MediaWiki 跑起来,数据库也塞在同一个容器里。这在测试环境没什么问题,但企业级环境绝对不能这么干,原因很简单:数据库是状态最重的部分,Wiki 代码坏了可以重新拉镜像,数据丢了就是灾难。

推荐方案是把服务拆成三个角色,用 Docker Compose 统一编排:

  • MediaWiki 应用容器:跑 PHP + Apache/FPM,负责处理请求和执行业务逻辑,属于无状态服务
  • 数据库容器:用 MariaDB 或 MySQL 的官方镜像,数据目录挂载到宿主机磁盘,承担全部内容存储
  • 反向代理容器:用 Nginx 终结外部流量,统一处理 HTTPS 证书,把请求转发给 Wiki 应用

数据库单独跑一个容器,核心收益是数据目录可以独立挂载、备份和恢复。即使 MediaWiki 容器被误删或者版本升级失败,数据库资源还在,重新拉一个应用容器挂上去就能恢复服务。如果你所在团队已经有现成的 MySQL 集群,也可以让 MediaWiki 容器直接连集群地址,宿主机上少跑一个数据库容器,运维压力更小,但前提是集群的编码、账号权限都要为 MediaWiki 做好配比。

2.2 版本、硬件与存储策略怎么选

版本选择是部署前最容易忽略、也最影响后续维护的环节。MediaWiki 官方对版本有自己的策略:只有最新稳定版才处于完整维护期,旧版本只做安全修补,再老的就直接停止支持。建议始终使用当时的最新稳定版镜像,尽量不要因为"看着顺手"就停留在两年前的版本。另外要注意镜像 tag 不要用 latest,要用明确的版本号,比如 mediawiki:1.42,这样保证不同时间部署出来的环境是可控的。

硬件方面,MediaWiki 对机器要求不算苛刻,但企业级场景里并发和搜索压力会很明显。内部知识库规模在几百人团队时,建议至少给 4 核 CPU 和 8GB 内存,其中数据库能分到 4GB 以上。磁盘优先用 SSD,尤其是 MySQL 的数据目录,机械盘在并发写入时会明显拖慢页面保存速度。服务器上持久化存储的挂载方式也要提前规划好,/var/lib/docker/volumes 这种 docker volumes 管理起来方便,但数据突然增长后不好清理;更常用的做法是把数据目录直接 bind mount 到宿主机专门的目录,例如 /data/mediawiki/db,这样备份脚本可以直接读取宿主机文件,不用再绕一层 docker 卷。

3. 基于 Docker Compose 的完整部署实操

3.1 目录结构与基础 Compose 文件编写

先规划好宿主机目录。我这里采用的是最常见的布局,一目了然,备份恢复也方便:

/data/mediawiki/ ├── compose.yaml ├── db/ │ └── data/ # 数据库数据目录 ├── wiki/ │ ├── LocalSettings.php # 安装完成后生成 │ └── images/ # 上传图片目录 ├── backups/ │ └── db/ # 数据库备份文件 └── logs/ └── nginx/ # 反向代理日志

这样组织的好处是:应用代码、数据库文件、备份文件、日志完全分离,做权限控制时可以各自指定归属;排查问题时也很直观,知道该去哪个目录找什么。

Compose 文件我建议用下面的版本起步,是官方镜像和常见实践组合出来的相对稳妥的搭配:

version: "3.8" services: mediawiki: image: mediawiki:1.42 container_name: mw_app restart: always volumes: - ./wiki/LocalSettings.php:/var/www/html/LocalSettings.php - ./wiki/images:/var/www/html/images depends_on: - database networks: - mw_net database: image: mariadb:11.1 container_name: mw_db restart: always environment: MYSQL_DATABASE: mediawiki MYSQL_USER: mwuser MYSQL_PASSWORD: "换成强密码" MYSQL_ROOT_PASSWORD: "换成另一个强密码" command: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci volumes: - /data/mediawiki/db/data:/var/lib/mysql networks: - mw_net nginx: image: nginx:1.26 container_name: mw_nginx restart: always ports: - "80:80" - "443:443" volumes: - ./nginx/conf.d:/etc/nginx/conf.d - /data/mediawiki/logs/nginx:/var/log/nginx depends_on: - mediawiki networks: - mw_net networks: mw_net: driver: bridge

几个关键点解释一下。mediawiki容器的两个挂载文件里,LocalSettings.php 是安装结束后才生成的,但建议提前挂载,这样生成后直接落到宿主机;images 目录则是 Wiki 上传文件存放的位置,很多权限问题都出在这个目录。数据库容器单独指定了 utf8mb4 字符集,这是中文内容不出现乱码的前提。容器之间通过自定义的桥接网络通信,方便互相解析服务名,也避免把端口暴露到公网。

3.2 数据库容器初始化与编码问题

启动顺序上有个细节值得注意。很多第一次部署的人会先启动所有容器,结果发现 MediaWiki 安装向导里数据库地址填了database却连接失败。这不是配置写错,而是 MediaWiki 容器先于数据库启动,或者数据库还在初始化阶段。Compose 里的depends_on只是保证启动顺序,不等数据库就绪。稳妥的做法是先把数据库容器单独启动,等待它初始化完成,再启动整个编排:

docker compose up -d database docker compose logs -f database # 看到 ready for connections 字样再继续

数据库第一次初始化耗时取决于硬件,机械盘可能要一两分钟,SSD 上大约十几秒。初始化完成后,建议通过宿主机上的客户端确认一下字符集:

SHOW VARIABLES LIKE 'character_set%';

如果character_set_server不是utf8mb4,说明 compose 文件里的 command 参数没有正确生效,需要检查是否有语法问题。企业级中文 Wiki 里,最常见的乱码问题根源就是这里,前期检查一下能省掉后面很多麻烦。

3.3 MediaWiki 安装向导与 LocalSettings.php 生成

数据库就绪后,启动全部容器:

docker compose up -d

浏览器访问http://服务器IP,正常情况下会跳转到 MediaWiki 的安装向导页面。填写数据库信息的时候,数据库地址不是localhost,而是要填database,也就是 Compose 网络里的服务名;数据库名和用户名填 compose 文件里设定的值;表前缀可以根据团队习惯选择留空或加mw_,我个人建议加上前缀,给未来在同一数据库实例上跑多个 Wiki 留出余地。

安装完成前,向导会让你生成一份 LocalSettings.php。点击下载后,直接把这份文件放到宿主机对应位置:

cp LocalSettings.php /data/mediawiki/wiki/LocalSettings.php

此时页面下方的提示会要求你把这份文件的内容复制到 MediaWiki 容器里,但因为我们挂载了文件出来,重新加载页面即可生效。这份文件里包含数据库账号密码,权限要收紧,建议设为 600,仅允许运行用户读取。

这里多说一句:很多团队的 Wiki 装完就完事了,后续换人维护时根本不知道当初改过哪些配置。我的习惯是在 LocalSettings.php 里按照功能分段写注释,比如数据库连接、缓存、上传、扩展、安全加固,每段都标注当时添加的原因,后续排查就能快速定位是哪段配置引起的异常。

3.4 接入 Nginx 反向代理和 HTTPS 证书

MediaWiki 自带的 Web 服务可以直接用,但企业级场景下几乎都会在前面加一层 Nginx 反向代理。原因有两个:一是统一处理 HTTPS 证书,让 Wiki 域名走安全的访问链路;二是 Nginx 对静态文件处理的效率比 PHP-FPM 高不少,页面加载速度会有肉眼可见的提升。

新增一个 Nginx 配置文件,核心内容类似下面这样:

server { listen 443 ssl http2; server_name wiki.example.com; ssl_certificate /etc/nginx/ssl/wiki.crt; ssl_certificate_key /etc/nginx/ssl/wiki.key; client_max_body_size 20m; location / { proxy_pass http://mediawiki:80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }

mediawiki在 Nginx 容器里同样解析为 Compose 网络中对应的服务 IP,所以这段配置直接可以用。client_max_body_size要按你实际的上传文件大小调整,默认 1M 会让大文件上传直接返回 413,我见过很多团队第一反应以为是自己代码问题,查了半天其实是 Nginx 的默认限制在拦截。证书方面,内网环境推荐使用自建 CA 签发的证书,配合客户端下发根证书后浏览器就不会报错;有公网域名的则直接用 Let's Encrypt 自动签发,省心很多。

4. 企业级加固:缓存、安全与备份恢复

4.1 接入 Memcached 提升并发能力

MediaWiki 默认配置下,每个页面请求都要读写数据库,几十个人同时访问可能没感觉,但在几百人的内网环境里,文章列表页和热门词条页的数据库压力会瞬间上来。缓存接入几乎是企业级部署的必选项。

先添加一个 Memcached 容器:

memcached: image: memcached:1.6 container_name: mw_memcached restart: always command: - -m 1024 networks: - mw_net

然后在 LocalSettings.php 中追加:

$wgMainCacheType = CACHE_MEMCACHED; $wgMemCachedServers = [ 'memcached:11211' ]; $wgObjectCaches['memcached'] = [ 'class' => 'MemcachedBagOStuff', 'servers' => [ 'memcached:11211' ], ];

-m 1024是给 Memcached 分配 1GB 内存,具体大小根据 Wiki 的页面数量和活跃用户数调整。接入缓存之后,最直观的变化是首页和导航栏这类高访问页面的响应速度明显提升。我实测过一套没有缓存和加了缓存同一台机器的对比,热门页面的请求耗时能下降一半以上,数据库的 CPU 占用也平稳了不少。

4.2 安全加固的关键配置

企业级 Wiki 在安全上需要有两个层面考虑:一是服务自身的安全加固,二是容器层面的最小权限配置。

MediaWiki 配置方面,有几项建议直接加上。上传文件的类型要限制,不能允许 PHP、脚本类文件上传到 images 目录,防止上传功能被利用来执行恶意脚本:

$wgFileExtensions = [ 'png', 'gif', 'jpg', 'jpeg', 'svg', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx' ]; $wgCheckFileExtensions = true; $wgVerifyMimeType = true;

同时禁止通过直接 URL 访问 images 目录里的 PHP 文件,这个可以在 Nginx 配置里加一条 location 规则。账号密码策略上,建议开启双重验证插件,至少要让管理员账号处于受保护状态,内部信息系统里管理员权限被攻破往往是重大安全事故的起点。

容器层面,不要为 MediaWiki 容器分配 root 权限,镜像里有内置的非 root 用户,可以通过 user 字段指定。数据库端口不要映射到宿主机,只保留在 Compose 网络内部即可。线上环境我见过有人图方便把3306:3306映射出来,结果数据库被扫到,弱密码被爆破,教训很深刻。

4.3 自动化备份与恢复演练

再好的高可用方案也替代不了可恢复的备份。企业级 Wiki 的数据分两部分:一部分是 MySQL 里的页面内容、用户账号、权限配置,另一部分是 images 目录里的上传文件。两者要分别备份。

数据库备份建议使用宿主机上的定时任务,每天凌晨执行一次,保留最近 7 天:

mysqldump -h 127.0.0.1 -P 3306 -u backup -p密码 \ --single-transaction --routines --triggers \ mediawiki | gzip > /data/mediawiki/backups/db/wiki_$(date +%F).sql.gz

要执行这个命令,前提是数据库容器把端口暴露给了宿主机,或者可以用 docker exec 进容器执行 mysqldump。我更推荐第二种方式,因为更安全:

docker exec mw_db sh -c \ 'mariadb-dump -u root --password=$MARIADB_ROOT_PASSWORD mediawiki' \ | gzip > /data/mediawiki/backups/db/wiki_$(date +%F).sql.gz

用--single-transaction可以保证备份期间不锁表,在线备份不影响正常使用。images 目录直接 rsync 到备份服务器或者另一个磁盘,再配合定期把备份文件同步到异地存储,做到"即使整台服务器宕掉也能恢复"的底线。

备份不能只做了不管,恢复演练同样重要。每季度至少做一次全量恢复演练:把备份文件恢复到一台临时服务器,确认页面内容、图片、扩展设置都能正常加载。没有经过验证的备份,真到灾难发生的时候很可能等于没有备份。

5. 常见问题排查与经验避坑

5.1 数据库连接不上的四个原因

实际部署中,数据库连接问题大概占了一半的故障排查量。我总结下来主要有四个原因:

第一,数据库地址填错。在 Docker Compose 网络里,地址必须是服务名database而不是localhost,这个最容易被新手踩中。第二,数据库容器还没完全就绪,MediaWiki 就已经启动了。解决方式是启动后查看数据库容器日志,确认看到 ready 相关提示再进行后续操作。第三,账号权限没有生效。MYSQL_USER 环境变量在容器初始化时创建的用户,默认只对 MYSQL_DATABASE 指定的库有权限,如果之后改了数据库名但没有同步修改变量,就会连接失败。第四,使用了错误的端口映射或主机地址。如果 MediaWiki 容器连宿主机上的数据库,需要映射端口并用宿主机 IP,这个场景最容易出现 localhost vs 实际 IP 的混乱。

排查这类问题有个顺手的小技巧:进入 MediaWiki 容器,直接尝试用 PHP 代码连接数据库,能快速定位是网络层问题还是账号权限问题。

5.2 上传文件失败的权限与参数问题

上传图片或附件失败,报错五花八门,但核心大多出在文件和目录权限上。MediaWiki 容器内的用户和宿主机用户 UID 不一致时,挂在 images 目录就可能出现没有写权限的情况。最直接的办法是在宿主机上把目录属主改成与容器内用户相同的 UID:

chown -R 33:33 /data/mediawiki/wiki/images

UID 33 是 Debian 系镜像中 www-data 用户的 ID,用宿主机命令确认后即可。如果配置了 Nginx 反向代理,还要检查client_max_body_size是否足够大,以及 PHP 上传限制是否打开。这两个参数都过小的时候,上传大文件会出现中断或状态码 413 的情况。在 LocalSettings.php 里可以显式配置上传相关参数,比如允许的文件大小上限$wgMaxUploadSize,并确保容器内 PHP 的 upload_max_filesize 不低于这个值。

5.3 升级版本时的容器迁移坑

MediaWiki 版本升级是维护期最让人紧张的操作,尤其是跳了大版本的时候。跳过多个大版本直接升级,偶尔会遇到数据结构不兼容的问题。稳妥的流程应该是:先备份全量数据和 images 目录;修改 compose 文件里的镜像 tag,升级到相邻的大版本;启动后访问mw-config目录,按提示运行升级脚本;确认页面正常后再继续下一步升级。

这里需要特别关注自定义配置的迁移。很多团队在 LocalSettings.php 里加了大量扩展配置,如果某个扩展版本与新版本不兼容,轻则功能异常,重则整个 Wiki 打不开。升级前先看扩展的兼容性声明,把不兼容的扩展先停用,升级完成后逐个启用并测试。此外,升级过程中数据库表结构的变更可能需要额外时间,量大的情况下页面会短暂不可访问,建议安排在低峰时段执行,并提前在团队通讯群里做好通知。

最后分享几点我自己实际运维的心得

Docker 部署 MediaWiki 本身不算难,难的是后续的长期稳定运行。我个人的感受是,环境能简化的事情就应该简化到极致,Compose 文件就是你的"环境文档",任何新的运维同事接手都可以顺着这份文件快速了解整个拓扑。命名、注释、网络划分这些细节,前期花十分钟做规范,后期能省出大量沟通和排障时间。

另外建议把 LocalSettings.php 纳入公司内部的版本管理系统,配置变更记录都有迹可循。Wiki 平台最怕的不是功能缺失,而是没人知道它被改过什么,出问题的时候无从下手。每次改动前想清楚对你最重要的场景是什么,不做没有目的的复杂扩展。MediaWiki 的生态很丰富,但企业级稳定运行,克制比炫技重要得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询