当前位置: 首页 > news >正文

第16篇 实战:用 Docker Compose 编排 WordPress 与 MySQL

IT策士 10余年一线大厂经验,专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章,助你少走弯路。

到目前为止,我们的贯穿案例一直是 Flask + Redis 计数器。它足够经典,但有些读者可能会觉得“太轻量”了——毕竟只有两个服务,依赖关系也很简单。在实际工作中,你编排的应用栈往往更复杂:有前端有数据库,数据库还需要初始化 root 密码,Web 服务器必须等待数据库完全就绪才能连接。

今天我们就来编排一个更真实的应用栈——WordPress + MySQL。这个案例涉及到了完整的环境变量管理、启动顺序控制、数据持久化,以及一个你在生产环境中必然会遇到的问题:数据库密码等敏感信息该如何处理。通过这个实战,你将看到前几篇学到的概念是如何在一个更复杂的场景中串联起来的。

一、为什么选 WordPress + MySQL?

WordPress 是全球使用最广泛的内容管理系统,它由两个核心组件构成:

  • WordPress:PHP 编写的 Web 应用,处理前端请求

  • MySQL:关系型数据库,存储文章、用户、配置等数据

这个组合是 Compose 教学中的经典案例,因为它天然涵盖了我们在第 11-15 篇学到的所有关键概念:WordPress 依赖 MySQL(启动顺序控制),MySQL 数据必须持久化(Volume),数据库密码等配置通过环境变量注入(敏感信息管理),以及服务间通过 DNS 解析互相发现(自定义网络)。可以说,掌握了 WordPress + MySQL 的编排,你就掌握了一般 Web 应用的编排范式。

二、Compose 文件完整配置

2.1 目录结构

wordpress/ ├── docker-compose.yml ├── .env# 环境变量(不提交到 Git)└── .gitignore

2.2 docker-compose.yml

services: db: image: mysql:8.0 restart: unless-stopped environment: -MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}-MYSQL_DATABASE=${MYSQL_DATABASE:-wordpress}-MYSQL_USER=${MYSQL_USER:-wordpress}-MYSQL_PASSWORD=${MYSQL_PASSWORD}volumes: - db-data:/var/lib/mysql networks: - wp-net healthcheck: test:["CMD","mysqladmin","ping","-h","localhost","-u","root","-p${MYSQL_ROOT_PASSWORD}"]interval: 10s timeout: 5s retries:5start_period: 30s wordpress: image: wordpress:6.7-php8.3-apache restart: unless-stopped ports: -"${WORDPRESS_PORT:-8080}:80"environment: -WORDPRESS_DB_HOST=db -WORDPRESS_DB_USER=${MYSQL_USER:-wordpress}-WORDPRESS_DB_PASSWORD=${MYSQL_PASSWORD}-WORDPRESS_DB_NAME=${MYSQL_DATABASE:-wordpress}volumes: - wp-data:/var/www/html networks: - wp-net depends_on: db: condition: service_healthy healthcheck: test:["CMD","curl","-f","http://localhost:80/wp-admin/install.php"]interval: 30s timeout: 10s retries:3start_period: 15s volumes: db-data: wp-data: networks: wp-net: driver: bridge

2.3 .env 文件

MYSQL_ROOT_PASSWORD=ChangeMeRoot123!MYSQL_DATABASE=wordpressMYSQL_USER=wpuserMYSQL_PASSWORD=ChangeMeUser456!WORDPRESS_PORT=8080

安全警告:以上密码仅为示例。在生产环境中,请使用强随机密码,不要将.env提交到版本控制系统,可考虑使用 Docker Secrets(Swarm 模式)或 Kubernetes Secrets 来管理。这里.env文件必须加入.gitignore,否则密码会被提交到 Git 历史。

三、关键配置解析

3.1 数据库服务(db)

MySQL 容器使用了几个关键环境变量:

  • MYSQL_ROOT_PASSWORD:MySQL root 用户密码,必须设置。MySQL 8.0 镜像在没有此变量时会报错退出。

  • MYSQL_DATABASE:容器启动时自动创建的数据库名。如果未指定,WordPress 将无法找到它的数据库。

  • MYSQL_USER/MYSQL_PASSWORD:创建一个普通用户并授予该数据库的全部权限(而不是直接用 root 连接,这是安全最佳实践)。

Volume 挂载db-data:/var/lib/mysql确保所有数据库文件持久化到命名卷中。即使容器被删除重建,数据也不会丢失。

健康检查使用mysqladmin ping,这是 MySQL 自带的轻量级探测工具,比mysql -e "SELECT 1"更高效。由于 MySQL 首次启动需要初始化数据目录(包括创建数据库和用户),start_period: 30s给了足够的时间窗口,避免在初始化期间被误判为 unhealthy。

3.2 WordPress 服务

WordPress 容器通过以下环境变量连接数据库:

  • WORDPRESS_DB_HOST:数据库主机名。这里写db,即 MySQL 服务的名称,Docker 内嵌 DNS 自动解析为 MySQL 容器的 IP。

  • WORDPRESS_DB_USER/WORDPRESS_DB_PASSWORD:连接数据库的凭证,与 MySQL 容器中创建的MYSQL_USERMYSQL_PASSWORD对应。

  • WORDPRESS_DB_NAME:要使用的数据库名,与MYSQL_DATABASE对应。

WordPress 在启动时会自动检测WORDPRESS_DB_HOST指定的数据库是否可用。如果数据库不存在或凭证错误,WordPress 会进入安装引导页面而不是正常运行。因此depends_on+service_healthy确保了它启动时 MySQL 已经接受连接。

3.3 启动顺序:depends_on + service_healthy

第 15 篇讲过的知识点在此完美落地:

depends_on: db: condition: service_healthy

Compose 会先启动db容器,然后每 10 秒执行一次mysqladmin ping,直到返回成功。只有 MySQL 健康检查通过后,wordpress容器才会被创建和启动。这避免了 WordPress 启动时 MySQL 还没准备好的竞态条件。

3.4 敏感信息管理

你可能会问:MySQL 密码直接写在.env文件里安全吗?

在单机 Compose 场景中,这是常用的折中方案——比硬编码在 YAML 中好,但仍然需要把.env加入.gitignore。生产环境中的更安全做法包括:使用 Docker Swarm 的 Secrets 功能,通过/run/secrets/挂载;在 Kubernetes 中使用 Secret 对象,并通过 Sealed Secrets 或 External Secrets Operator 加密后存入 Git。

.gitignore文件内容:

四、启动与验证

4.1 一键启动

# 在 wordpress 目录下执行dockercompose up-d

输出:

[+]Running4/4 ✔ Network wordpress_wp-net Created0.1s ✔ Volume"wordpress_db-data"Created0.0s ✔ Volume"wordpress_wp-data"Created0.0s ✔ Container db Started0.5s

注意,此时wordpress容器还没有启动。因为db容器虽然在运行,但健康检查还没有通过。等待约 30-40 秒,MySQL 完成首次初始化(创建数据库、用户、设置 root 密码),mysqladmin ping返回成功,Compose 才会启动 WordPress 容器。

dockercompose logs-fdb

观察 MySQL 初始化日志,当看到ready for connections时,表示 MySQL 已经就绪。

4.2 验证服务状态

输出:

NAME IMAGE STATUS wordpress-db-1 mysql:8.0 Up2minutes(healthy)wordpress-wordpress-1 wordpress:6.7-php8.3-apache Up1minute(healthy)

两个服务都标记为(healthy)

4.3 访问 WordPress

打开浏览器,访问http://localhost:8080。你会看到 WordPress 的安装向导页面,选择语言,设置站点标题、管理员用户名和密码,然后登录即可。

4.4 验证数据持久化

我们来模拟一次灾难恢复演练:

# 1. 先确认可以正常访问 WordPress 并完成初始化安装# 在浏览器中完成安装向导,设置管理员账号密码,登录后写一篇测试文章# 2. 模拟灾难:删除所有容器dockercompose down# 3. 检查数据卷仍然存在dockervolumels|grepwordpress# wordpress_db-data# wordpress_wp-data# 4. 重新启动(必须使用同一个 docker-compose.yml 和 .env)dockercompose up-d# 5. 检查日志dockercompose logs wordpress|grep"complete"# 不会出现安装向导,直接可以访问

访问http://localhost:8080,你之前写的测试文章仍然存在。数据卷确保了数据在容器销毁后不会丢失。

五、常见踩坑与解决

坑 1:MySQL 启动后 WordPress 连接报错

现象:WordPress 显示“建立数据库连接时出错”。

排查

# 查看 WordPress 日志dockercompose logs wordpress# 检查环境变量是否正确注入dockercomposeexecwordpressenv|grepWORDPRESS_DB# 确认 MySQL 确实在运行且健康dockercomposeexecdb mysqladminping-hlocalhost-uroot -p${MYSQL_ROOT_PASSWORD}

常见原因:.env文件未放置在正确位置(必须与docker-compose.yml同级),或MYSQL_PASSWORDWORDPRESS_DB_PASSWORD不一致。

坑 2:WordPress 首次启动卡在安装向导

这是正常行为!WordPress 镜像并不会自动完成安装向导(设置站点标题、管理员账号等)。你需要通过浏览器访问http://localhost:8080手动完成。完成安装后,WordPress 会在数据库中写入站点配置,之后重启容器不会再出现安装向导。

坑 3:端口冲突

现象:启动时提示Bind for 0.0.0.0:8080 failed: port is already allocated

解决:修改.env中的WORDPRESS_PORT=8081,或在启动时覆盖:

WORDPRESS_PORT=8081dockercompose up-d

六、从 WordPress 到 K8s

你可能已经注意到,WordPress + MySQL 这个案例中涉及的每个概念,在 Kubernetes 中都有对应的实现:

这就是第 18 篇将要详细展开的内容——从 Compose 到 Kubernetes 的概念映射。你此刻用 Compose 编排的每个步骤,在 K8s 中几乎都有 1:1 的替代方案,只是表达方式从 YAML 变成了更强大的声明式 API。

七、命令速查表

八、本篇总结

通过 WordPress + MySQL 这个实战案例,你将前面学到的 Compose 知识融会贯通:

  • 服务定义:两个服务通过services声明,Compose 自动创建容器。

  • 自定义网络wp-net让 WordPress 和 MySQL 通过服务名db互相通信。

  • 数据持久化:命名卷确保数据库文件和 WordPress 上传内容不随容器删除而丢失。

  • 启动顺序控制depends_on+service_healthy彻底解决了“数据库未就绪导致应用崩溃”的问题。

  • 配置管理:通过.env文件统一管理环境变量和敏感信息,避免硬编码。

  • 健康检查:MySQL 用mysqladmin ping,WordPress 用 HTTP 端点验证,确保服务真正可用。

下一篇——第 17 篇:Compose 进阶:多 Compose 文件与环境覆盖,我们将学习如何通过多文件组合和环境特定覆盖文件,让同一套 Compose 配置适配开发、测试、生产等多套环境,真正实现“一次编写,到处部署”。

想了解更多还可以去各个平台搜索「IT策士」,一起升级 IT 思维 !

http://www.gsyq.cn/news/1424672.html

相关文章:

  • AI搜索推广工具如何工程化落地:中科信枢龙虾智能体的内容资产与多平台分发架构
  • 神经形态计算π²架构:突破AI硬件能效瓶颈
  • 手把手教你用Python+sklearn计算classification_report(附多分类不平衡数据集实战)
  • 【2024最严AI监管倒计时】:Claude风险评估矩阵4.2版紧急升级清单(含GDPR/CCPA/《生成式AI服务管理暂行办法》三重映射表)
  • AI看懂“弦外之音“:中科院软件所等机构联合攻克视频隐喻理解难题
  • AI健康管家:大模型赋能私域健康服务,重塑新零售智慧运营体系
  • 石漠化区耕作污染的地下水微生物—毒理联合响应机制及模拟方法解析【附代码】
  • 上海厂区化粪池清理技术实操推荐:上海专业管道清洗/上海化粪池油污清理/上海化粪池清理电话/正规服务品牌参考 - 优质品牌商家
  • 浙江大学与伦敦大学学院联手打造“科学地图“
  • 每日算法快闪赛:高效刷题的技术秘籍
  • 基于Arduino与超声波传感器的智能停车辅助系统DIY指南
  • 别再浪费硬盘了!用Ubuntu的mdadm组RAID 0,榨干旧硬盘性能当高速缓存盘
  • 宇视VM易用性推宣—相机报表导出
  • 格式排版也能 “躺平”?okbiye 论文格式神器,让你和几十页格式指南说再见
  • 别再手动删点了!用Python的RDP算法5分钟搞定轨迹数据简化(附完整代码)
  • 网安圈的“世界杯”!一文讲透传说中的“护网行动”
  • 矫平机用着用着就出问题?这几类常见故障你该提前了解
  • 情感提示(Emotion Prompting)的原理是什么?“深呼吸“这类提示为什么有效?
  • 零基础学 PLC,千万不要一开始就报名,不想采坑必看
  • 如何通过Atmosphere大气层系统为你的Switch解锁终极性能
  • C++初阶 模版进阶
  • NTU、HKU等多所顶校联手,让AI同时“多角度看片“
  • AI Agent Harness Engineering 创业风险规避:市场、技术与政策的潜在坑点
  • 别再死磕理论了!用Python+PyTorch实战MAPPO,搞定多智能体协同控制(附完整代码)
  • 【Leetcode】231. 2的幂
  • TranslucentTB:Windows任务栏透明化终极指南与完整解决方案
  • 西湖大学等机构联手破解AI图像生成的“翻译失真“难题
  • 保姆级教程:在Ubuntu 20.04上从源码编译运行FAST-LIO2(避坑指南)
  • 2026年成都店面设计装修品牌实测评测对比 - 优质品牌商家
  • 【Lindy自动化黄金配置清单】:12项必检参数+3类高危人工干预场景预警