先把结论放前面:Docker部署维基萌博客系统,核心不是“把镜像拉下来跑起来”,而是把 Nginx、PHP-FPM、MySQL 三个容器的编排关系、数据持久化方案、网络配置和备份策略一次想清楚。这篇文章我会从零开始,把整个部署过程的思路、配置、踩坑点和排错方案完整写出来,照着做基本能一次跑通。
维基萌博客系统本身是典型的 PHP + MySQL 架构,这类程序手动部署时要装 PHP、配扩展、调 Nginx、建数据库,每一步都可能出问题;换成 Docker 之后,环境一致性、迁移便利性和后续版本升级都会省心很多。但 Docker 不是银弹,它把“环境问题”变成了“编排问题”,容器之间怎么通信、数据怎么持久化、镜像怎么选、故障怎么排查,反而是新手最容易卡住的点。这篇文章适合三类人:第一次接触 Docker 部署的博客站长、想把手动部署的 PHP 项目改成容器化部署的运维新人,以及需要在 Windows 或 Linux 上把 Docker 环境从零跑起来的客户端用户。
1. 部署前的思路拆解:为什么选择 Docker 而非裸机部署
1.1 维基萌博客系统的技术栈画像
维基萌博客系统这类自托管博客程序,几乎是 PHP 时代个人建站的标配形态:前端页面由 PHP 动态渲染,数据存放在 MySQL 中,静态资源(图片、CSS、JS)由 Nginx 直接返回。它的部署形态非常经典,也非常“吃环境”——PHP 版本要匹配、pdo_mysql和mysqli扩展不能缺、gd和mbstring等常用扩展跟着主题和插件走、Nginx 的伪静态规则必须符合程序的路由要求。
这套组合放在一台新服务器上手动装,至少要经历:安装 Nginx、安装 PHP-FPM、装扩展、改配置、建库建账号、上传程序、跑安装向导、调伪静态。任何一个环节的版本不对、权限不对、扩展缺失,都会让安装向导走到一半卡死,或者首页白屏。我印象最深的一次,是在一个旧系统上手动部署,PHP 默认没开pdo_mysql,我当时没注意,结果安装向导一直报"数据库连接失败",排查了快两个小时才发现是扩展问题。
用 Docker 部署的核心价值就在这里:把 PHP、Nginx、MySQL 分别封装成独立容器,每个容器只负责一件事,版本在镜像里固定好,扩展通过 Dockerfile 一次性装齐。换一台机器,只要把编排文件和挂载目录带过去,一条命令就能还原整个环境。对于维基萌博客这种个人级项目,容器化之后最大的收益不是性能,而是“可复现”和“可迁移”。
1.2 Docker 编排带来的收益与代价
Docker 部署博客系统的收益非常直接:
- 环境隔离。博客程序依赖的 PHP 扩展库、MySQL 版本不会污染宿主机,也不会跟宿主机上其他服务冲突。
- 快速迁移。
docker-compose.yml加挂载目录,压缩打包后到新服务器上docker compose up -d,数据直接回来。 - 版本控制。镜像 tag 锁死版本,升级时只需换 tag 并测试回滚,不用在服务器上卸载重装。
- 故障恢复。容器挂了
restart: unless-stopped会自动拉起,MySQL 数据在宿主机目录里,容器删了不丢数据。
代价同样明显:第一,多了一层抽象,出了问题要先判断是容器问题还是应用问题;第二,容器之间的网络通信对新手来说是个认知门槛,主机名、端口映射、网络模式的概念得理解;第三,数据持久化如果没做好,docker compose down之后数据全没了,这会直接劝退一批刚入门的人。
所以我的建议是:动手之前先把挂载目录、服务名、端口映射这三个概念想清楚。在 Docker 里,MySQL 的地址不是localhost,而是服务名mysql;页面文件不是放在服务器/var/www/html,而是放你宿主机上映射过去的目录。这些思维转换是部署成功的关键,后续所有配置都围绕这三个概念展开。
2. 环境准备:先把 Docker 引擎跑起来
2.1 Linux 服务器上的 Docker 安装与验证
我部署维基萌博客的主机是一台 Ubuntu 22.04 的云服务器,Linux 下安装 Docker 最简单的方式是用官方安装脚本,但考虑到很多人需要离线或指定版本安装,我更推荐先用 APT 仓库方式,这样后续升级和管理都方便。
# 更新软件源并安装依赖包 sudo apt update sudo apt install -y ca-certificates curl gnupg lsb-release # 添加 Docker 官方 GPG 密钥 sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg # 添加 Docker 软件源 echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # 安装 Docker 引擎 sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin装完先别急着用,验证一下服务和权限。
sudo systemctl enable --now docker sudo systemctl status docker sudo docker version很多新手装完 Docker 后执行docker ps会收到权限错误,提示“permission denied while trying to connect to the Docker daemon socket”。这是因为当前用户不在docker组里。把用户加进组并重新登录即可:
sudo usermod -aG docker $USER newgrp docker这里要啰嗦一句:docker组实际上等同于 root 权限,生产服务器上尽量只把可信的管理员用户加进去,别图方便所有账号都加。
2.2 Windows 与 macOS 上的 Docker Desktop 常见问题
如果你的开发机是 Windows,想先在本地把维基萌博客跑起来再上服务器,那就需要 Docker Desktop。Windows 上 Docker Desktop 最常见的启动失败场景有两个,一个是“Virtualization support not detected”,一个是“failed to connect to the Docker api at npipe:////./pipe/dockerdesktoplinuxen”。
第一个问题的根因是 Windows 的虚拟化平台没打开。Docker Desktop 依赖 WSL2 或 Hyper-V 来运行 Linux 内核,BIOS 里的虚拟化技术(Intel VT-x / AMD-V)如果被禁用,或者 Windows 功能里的“虚拟机平台”没开启,就会出现这个报错。解决方法:在 BIOS 里打开虚拟化开关,然后在 PowerShell(管理员)里执行:
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart执行完重启,再启动 Docker Desktop。“failed to connect to the docker api”这个报错多半是 Docker Desktop 的 WSL 后端没起来,可以先退出 Docker Desktop,在终端执行wsl --shutdown再重新打开,如果反复失败就检查 Windows 版本是否过旧,优先升级到最新稳定版。
macOS 上的问题少一些,主要是 M 系列芯片的内存分配。Docker Desktop 默认只分 2GB 内存给虚拟机,跑 Nginx+PHP+MySQL 三个容器会很吃力,建议在 Docker Desktop 的 Settings -> Resources 里把内存调到 4GB 以上,CPU 调到 4 核以上。否则容器能启动,但页面响应特别慢,甚至 PHP-FPM 频繁被杀。
2.3 镜像拉不下来的处理思路
部署维基萌博客需要从 Docker Hub 拉取php、nginx、mysql等镜像。国内网络环境下,直接拉 Docker Hub 经常会出现超时或速度极慢的情况,这是很多新手一开始就卡住的地方。
解决方案不是去碰网络代理,而是配置镜像加速地址。Docker Desktop 里在 Settings — Docker Engine 的 JSON 配置中加入 registry-mirrors;Linux 系统则在/etc/docker/daemon.json中配置:
{ "registry-mirrors": [ "https://docker.m.daocloud.io", "https://dockerproxy.net" ] }也可以在云厂商(如阿里云、腾讯云)的容器镜像服务控制台获取专属加速地址,稳定性更高。配置完记得重启 Docker 服务:
sudo systemctl restart docker我实测下来,配置镜像加速之后拉取mysql:8.0和nginx:1.24-alpine的速度能从原来的十几分钟降到几十秒。还有一个小技巧:如果某个镜像还是慢,可以先用加速地址拉取再重新打 tag。不过绝大多数场景下,配好daemon.json就够了。
3. 镜像选型与目录规划
3.1 Web 与数据库镜像的选择逻辑
维基萌博客系统的运行环境是 PHP + MySQL,镜像选择上主要考虑体积、稳定性和扩展支持。我选的是php:8.2-fpm-alpine,因为 Alpine 版体积小、内存占用低,适合个人博客这种低负载场景。nginx:1.24-alpine同理。数据库方面,我用了mysql:8.0,如果你想更省内存,换成mariadb:10.11也完全没问题,兼容性很好。
这里有个值得注意的点:php:8.2-fpm-alpine镜像默认带的 PHP 扩展并不全,维基萌博客需要pdo_mysql、mysqli、gd、mbstring等扩展,我直接把定制扩展的步骤写进 Dockerfile,这样镜像每次构建出来都自带完整的运行环境,不用每次启动容器后手动进容器装扩展。
FROM php:8.2-fpm-alpine # 安装系统依赖 RUN apk add --no-cache libpng-dev libjpeg-turbo-dev freetype-dev icu-dev oniguruma-dev # 安装 PHP 扩展 RUN docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install -j$(nproc) pdo_mysql mysqli mbstring exif zip gd RUN docker-php-ext-enable pdo_mysql mysqli mbstring exif zip gddocker-php-ext-install是 PHP 官方镜像提供的扩展编译脚本,它会自动调用源码目录里的扩展编译流程。不同的博客程序对扩展的要求不一样,维基萌这类程序还可能需要curl、opcache,所以建议先看程序文档确定所需扩展列表,再改 Dockerfile。如果遇到某个扩展编译失败,优先检查是不是少了系统依赖包,比如gd扩展就需要libpng-dev、freetype-dev这些编译库。
3.2 数据挂载目录规划
Docker 容器是“无状态”的,容器销毁后内部文件全部清空。为了让维基萌博客的数据真正安全,容器启动前就要规划好宿主机挂载目录。我的目录结构如下:
~/wikimoe/ ├── docker-compose.yml ├── Dockerfile ├── .env ├── www/ # 博客程序文件 │ └── index.php ├── data/ │ └── mysql/ # MySQL 数据库文件 ├── nginx/ │ ├── conf.d/ │ │ └── wikimoe.conf │ └── certs/ └── logs/ └── nginx/这里最容易被忽略的是www目录的挂载方式。Nginx 容器和 PHP-FPM 容器都要访问 PHP 文件,所以我让两个容器都挂载同一个./www目录,Nginx 负责处理静态文件和转发动态请求到 PHP-FPM,PHP-FPM 负责解析 PHP 文件,两边看到的文件路径保持一致(都是/var/www/html),才能正确协作。
MySQL 的数据目录挂载到./data/mysql,即使容器被删掉、重新创建,数据库文件也都在宿主机上。logs/nginx挂载进去是为了方便直接查看 Nginx 的访问日志和错误日志,排查问题不用进容器。.env文件里放数据库密码等敏感信息,不要直接写死在docker-compose.yml里。
4. 编写 docker-compose.yml:三个容器的编排与通信
4.1 整体编排结构
docker-compose.yml是部署的核心文件,它把 MySQL、PHP-FPM、Nginx 三个服务定义清楚,包括镜像、端口、挂载、网络、依赖关系。我贴一个有代表性的完整版本,你可以直接抄:
version: "3.8" services: mysql: image: mysql:8.0 container_name: wikimoe-mysql restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} MYSQL_DATABASE: wikimoe MYSQL_USER: wikimoe MYSQL_PASSWORD: ${DB_PASSWORD} volumes: - ./data/mysql:/var/lib/mysql networks: - wikimoe-net healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-proot123"] interval: 10s timeout: 5s retries: 10 command: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci php: build: context: . dockerfile: Dockerfile container_name: wikimoe-php restart: unless-stopped volumes: - ./www:/var/www/html networks: - wikimoe-net depends_on: mysql: condition: service_healthy nginx: image: nginx:1.24-alpine container_name: wikimoe-nginx restart: unless-stopped ports: - "80:80" volumes: - ./www:/var/www/html - ./nginx/conf.d:/etc/nginx/conf.d - ./logs/nginx:/var/log/nginx networks: - wikimoe-net depends_on: - php networks: wikimoe-net: driver: bridge注意depends_on的区别:Nginx 只依赖 PHP(depends_on: - php),PHP 依赖 MySQL 且要求健康检查通过(condition: service_healthy)。这样保证了启动顺序:MySQL 先就绪,PHP-FPM 再启动,Nginx 最后起来。如果不用service_healthy,PHP 容器可能在 MySQL 还没初始化完就启动,连接数据库时就会报错,这也是“容器起来了但博客安装向导连不上数据库”的高频原因之一。
command里我加了 MySQL 的字符集参数,设置utf8mb4。这个非常关键:现代博客程序普遍需要存储 emoji 表情,如果是默认的latin1或utf8mb3,插入表情符号会直接报错,或者存进去以后变成问号。
4.2 服务名通信与端口映射
容器之间通信不靠 IP,靠服务名。在docker-compose.yml里,三个服务同处wikimoe-net网络,因此在 PHP 容器内连接数据库时,数据库地址直接填mysql,而不是localhost或127.0.0.1。同理,Nginx 把 PHP 请求转发给 PHP-FPM 时,目标地址是php:9000。
这里有个很容易坑到新手的点:如果数据库连接填了localhost,PHP-FPM 容器会认为数据库在它自己容器内部,但实际上容器里根本没有 MySQL,必然连接失败。正确写法要填服务名mysql。
端口映射方面,ports: "80:80"表示宿主机 80 端口映射到容器 80 端口。如果你想用 8080 访问,写"8080:80"即可。端口映射只暴露在宿主机层面,容器间通信走的是内部网络,不受端口映射限制。这个设计的好处是:Nginx 容器没必要对外暴露 3306 端口,MySQL 只在内网被 PHP 访问,外部根本碰不到数据库,减少了被攻击的面。
4.3 PHP-FPM 与 Nginx 配置要点
Nginx 容器启动时会加载/etc/nginx/conf.d目录下的站点配置,我直接写一个wikimoe.conf放到./nginx/conf.d/下,覆盖掉默认配置。配置的核心是 fastcgi 转发:
server { listen 80; server_name blog.example.com; root /var/www/html; index index.php index.html; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass php:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { expires 30d; add_header Cache-Control "public, immutable"; } }fastcgi_pass php:9000里用的php就是 compose 文件里的服务名,这跟数据库连接用mysql是同一个道理。SCRIPT_FILENAME必须用$document_root$fastcgi_script_name,因为 Nginx 和 PHP-FPM 看到的都是同一个挂载目录/var/www/html,这样 PHP 才能正确找到要执行的文件。我之前遇到过一次 404,就是因为这里写成了$document_root$request_filename,在部分版本下解析路径不对。
静态文件缓存这段也可以加上。博客的图片和前端静态资源不会频繁变化,设一个 30 天的expires能明显提升首屏速度。浏览器第二次打开页面时,大部分静态资源直接走本地缓存,不再请求服务器。
5. 部署实操全流程:从空目录到安装向导
5.1 启动容器与观察日志
文件都准备好之后,进入~/wikimoe目录,第一次启动执行:
docker compose build docker compose up -dbuild会先构建 PHP 镜像,首次构建因为要下载基础镜像和编译扩展,耗时取决于网络和环境,一般在 5 到 15 分钟。构建完成后up -d会在后台启动所有服务。查看服务状态:
docker compose ps docker compose logs -f mysql docker compose logs -f php docker compose logs -f nginx这一步我建议仔细看日志。MySQL 容器首次初始化时会创建数据库、账号、字符集配置,日志里会出现“Initializing database”“ready for connections”这样的关键字,看到“ready for connections”再继续后续操作。如果日志里出现ERROR 1045 Access denied,大概率是.env里的密码变量没写对,或者环境变量没生效,先检查.env文件再继续。
5.2 博客系统的安装向导配置
三个容器都正常运行后,在浏览器里访问http://服务器IP或http://localhost,浏览器默认端口是 80,所以这里不需要额外加端口号。正常情况下会进入维基萌博客系统的安装向导页面。
安装向导需要填数据库信息时,数据库地址填mysql,端口填3306,数据库名填wikimoe,用户名填wikimoe,密码填.env里设置的DB_PASSWORD,不要用 root 连接应用。这是我一直坚持的习惯:应用账号只给当前数据库的权限,不给 root 权限,万一程序被注入,攻击者也拿不到数据库管理权限。
数据库连接成功后,向导会要求设置管理员账号、博客标题、时区等信息。这里我特别提醒一下:安装向导里的“站点地址”(site URL)直接决定了后续伪静态规则的生成,如果服务器 IP 或域名写错,之后后台链接全都不对,需要重新配置数据库里的options表,麻烦得很。所以安装时就要把最终对外访问的域名或 IP 写正确。
5.3 域名绑定与 HTTPS 配置
安装完成后用 IP 访问可能一切正常,但正式使用最好绑定域名。域名解析到服务器 IP 之后,把 Nginx 配置里的server_name改成你的域名,重启 Nginx 容器:
docker compose exec nginx nginx -t docker compose restart nginx域名访问测试没问题,就可以上 HTTPS。我目前用的方式是用可自动续期的证书管理工具,配合反向代理容器,也能在 Nginx 里手动配置证书。如果你手头已有证书,把.pem和.key文件放到./nginx/certs/目录,再修改wikimoe.conf:
server { listen 443 ssl http2; server_name blog.example.com; ssl_certificate /etc/nginx/certs/blog.pem; ssl_certificate_key /etc/nginx/certs/blog.key; # 其余配置同上 } server { listen 80; server_name blog.example.com; return 301 https://$host$request_uri; }改完配置后测试并重载 Nginx。同时别忘了把个人信息、联系方式、密码这类敏感数据连同验证/签发流程全部落到数据库和配置文件中严格管理签名和权限,证书私钥文件的权限要确保只有 root 可读,防止被下载。
6. 常见问题与排查技巧实录
6.1 Docker 部署维基萌博客的排错速查表
部署过程中一定会遇到问题。我把运行维基萌博客时最常见的几种情况整理成表格,结合排查思路一起看:
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| 页面显示 502 Bad Gateway | Nginx 连不上 PHP-FPM | 检查fastcgi_pass php:9000是否指向正确服务名;用docker compose ps确认 php 容器是否在运行 |
| 页面显示 404 | Nginx 找不到 PHP 文件或伪静态规则不对 | 检查root路径是否与挂载目录一致;检查try_files规则是否配置 |
| 安装向导连不上数据库 | 数据库地址填错或 MySQL 未就绪 | 确认数据库地址填mysql而不是localhost;查看 mysql 容器健康日志 |
| 数据库中文乱码或 emoji 变问号 | 字符集没配对 | 确认 MySQL 启用了utf8mb4,博客程序连接参数也使用utf8mb4 |
| 容器反复重启 | 端口被占用或健康检查失败 | docker compose logs查看具体报错;检查宿主机 80/3306 端口是否被占用 |
| 页面加载慢 | 宿主机内存不足或 PHP-FPM 配置过低 | 调整php-fpm的pm.max_children参数;给宿主机增加内存或 Swap |
| Docker 命令提示权限错误 | 当前用户不在 docker 组 | sudo usermod -aG docker $USER后重新登录 |
排错的第一原则是:先看日志,别瞎猜。docker compose logs [服务名]能看到容器内进程的输出,95% 的问题都能从日志里找到直接线索。比如 502 的日志会明确告诉你connect() failed (111: Connection refused) while connecting to upstream,这时候就知道是 PHP-FPM 没起来或者地址写错。
第二个原则是:分清问题出在宿主机还是容器。在宿主机执行curl http://localhost能返回页面,说明 Nginx 正常;如果返回超时,检查防火墙是否放行了 80 端口。在容器内部执行docker compose exec php php -v,如果 PHP 命令能正常输出版本信息,说明应用环境正常。逐层缩小范围,问题定位就快很多。
6.2 备份与恢复:Docker 部署避坑最后一关
写完博客内容,数据就是最宝贵的资产。Docker 部署的备份逻辑比裸机部署简单:只要备份两个东西,MySQL 数据目录和博客文件目录。
MySQL 备份我用官方自带的逻辑备份工具,进入容器执行:
docker compose exec mysql sh -c 'exec mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" --all-databases --single-transaction --quick --lock-tables=false' > backup_$(date +%Y%m%d_%H%M%S).sql--single-transaction是 InnoDB 在线备份的推荐参数,它利用事务的隔离级别实现无锁备份,备份过程中博客照常读写,不会阻塞访问。备份出来的 SQL 文件压缩后存到单独的备份目录。
恢复数据库时,把备份文件拷回服务器,执行:
cat backup.sql | docker compose exec -T mysql sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"'文件目录的备份就简单了,直接把./www目录打包,必要时同步到对象存储或另一台机器,恢复时解压覆盖即可。我个人的建议是:数据库每日备份一次,文件目录每周打包一次,备份放在和服务器不同的存储位置,防止服务器故障连带备份一起丢了。
恢复测试一定要做一次。找一台临时服务器,用同一个docker-compose.yml启动,导入备份文件,确认页面能正常打开、文章图片都在。备份只有经过恢复验证才算有效,这是我踩过坑后学到的教训——备份文件躺在那里几 TB,真要恢复时才发现在备份过程中数据库连接中断导致 SQL 文件损坏,那一刻的心情,经历过的人都懂。
7. 性能优化与安全加固的落地细节
7.1 PHP-FPM 与 MySQL 的资源适配
个人博客流量一般不大,但 Docker 默认配置未必适合实际运行。php:8.2-fpm-alpine镜像的默认进程池配置比较保守,如果你的服务器内存有 4GB,可以考虑适度调大进程数。修改www.conf的方式是:把改好的配置挂载进容器,或在 Dockerfile 里用sed修改默认配置。
pm = dynamic pm.max_children = 20 pm.start_servers = 5 pm.min_spare_servers = 3 pm.max_spare_servers = 8pm.max_children设置的是 PHP-FPM 最多同时处理的请求数,它不能盲目调大。每个 PHP 进程大约占 30-50MB 内存,如果你的服务器只有 2GB 内存,max_children调到 50 会导致内存耗尽,容器直接 OOM。合理估算方式是:内存总量除以单进程内存,留出 30% 余量给系统和其他容器。
MySQL 方面,个人博客数据量不大,最需要检查的是innodb_buffer_pool_size,默认 128MB 没问题,内存充足可以调到物理内存的 50%-60%。另外开启慢查询日志有助于定位慢 SQL。
7.2 安全加固的几个关键动作
修改默认端口。如果博客服务器的 SSH 和 MySQL 端口默认暴露在公网,会被扫描工具盯上。SSH 改到非标准端口,MySQL 容器不映射宿主机端口,只在 Docker 内网供 PHP 访问。这一步我在第一次部署就做了,效果立竿见影。
限制后台登录尝试。维基萌博客系统如果有登录验证码或次数限制就开启,没有的话建议加一层基础认证,或者限制后台路径只能从本机访问,防止爆破。
及时升级基础镜像。
php、nginx、mysql镜像要关注官方安全公告,有更新时先在测试环境跑一遍再升级。docker compose pull配合up -d可以无感更新到新镜像,但数据库大版本升级要谨慎,做好备份再动。容器网络最小化。维基萌博客实际只需要暴露 Nginx 的 80 端口,其他端口一律不映射出去。我在生产环境里只让宿主机对外开放 80 和 443,SSH 端口限定指定 IP 段,数据库端口完全不映射,整体暴露面小了很多。
8. 写在最后:我实际部署后的几点体会
这套 Docker 部署方案我自己实际跑了半年,中间经历过服务器迁移、镜像升级、数据库恢复演练,总体很稳。最大的体会是:先把 compose 文件和目录结构理清楚,比任何一步都重要。网上很多教程只给一个精简的docker run命令,把端口、挂载、环境变量混在一起,看着能跑,但后续维护非常痛苦,所以我一直坚持用docker-compose.yml管理,配置清晰、迁移方便、回滚也快。
最后再分享一个经验:维基萌博客的伪静态规则如果换了 Nginx 环境后页面全部 404,先别急着改代码,检查try_files $uri $uri/ /index.php?$query_string;里重写目标是不是index.php,很多博客程序其实是index.php?$args或直接index.php/路由,这个细节决定了伪静态能否生效。我自己就在这个问题上折腾过大半天。
如果你正准备把自己的博客系统迁到 Docker,或者第一次部署维基萌博客系统,这篇流程可以直接照着做。过程中如果卡在哪一步,优先看容器日志,再逐层排查网络、端口、数据持久化这几个层面,基本都能顺利解决。部署完成后,日后的更新、备份、迁移都会变得异常轻松。