首页 / 资讯中心 / 文章详情

MediaWiki+Docker企业级Wiki部署:从架构设计到运维实践

MediaWiki+Docker企业级Wiki部署:从架构设计到运维实践 ★ FEATURED ARTICLE
要在一家公司里搞一套企业级Wiki平台MediaWiki 基本是绕不开的选项。这个老牌开源 Wiki 引擎看着朴素但权限体系完整、扩展插件多、内容组织能力强特别适合做团队内部知识库。而 Docker 把 PHP 环境、数据库、依赖扩展这些最折腾人的部分直接容器化两者配在一起已经成为中小企业搭建内网 Wiki 的主流方式。这篇文章把从选型、架构设计、Docker Compose 部署、缓存接入、备份恢复再到常见问题排查的完整过程都梳理了一遍。我自己前后搭过好几套 MediaWiki有大几百人同时在用的内网知识库也有十几人的小团队协作站点很多坑是实际踩过了才总结出来的。文章里写的每一步都可以直接照着做不是那种只讲概念的泛泛之谈。1. 为什么企业级 Wiki 要选 MediaWiki Docker1.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-serverutf8mb4 - --collation-serverutf8mb4_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 签发的证书配合客户端下发根证书后浏览器就不会报错有公网域名的则直接用 Lets 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 目录就可能出现没有写权限的情况。最直接的办法是在宿主机上把目录属主改成与容器内用户相同的 UIDchown -R 33:33 /data/mediawiki/wiki/imagesUID 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 的生态很丰富但企业级稳定运行克制比炫技重要得多。
阅读完成 · 觉得有帮助?
咨询建站