IT策士 10余年一线大厂经验专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章助你少走弯路。到目前为止我们的贯穿案例一直是 Flask Redis 计数器。它足够经典但有些读者可能会觉得“太轻量”了——毕竟只有两个服务依赖关系也很简单。在实际工作中你编排的应用栈往往更复杂有前端有数据库数据库还需要初始化 root 密码Web 服务器必须等待数据库完全就绪才能连接。今天我们就来编排一个更真实的应用栈——WordPress MySQL。这个案例涉及到了完整的环境变量管理、启动顺序控制、数据持久化以及一个你在生产环境中必然会遇到的问题数据库密码等敏感信息该如何处理。通过这个实战你将看到前几篇学到的概念是如何在一个更复杂的场景中串联起来的。一、为什么选 WordPress MySQLWordPress 是全球使用最广泛的内容管理系统它由两个核心组件构成WordPressPHP 编写的 Web 应用处理前端请求MySQL关系型数据库存储文章、用户、配置等数据这个组合是 Compose 教学中的经典案例因为它天然涵盖了我们在第 11-15 篇学到的所有关键概念WordPress 依赖 MySQL启动顺序控制MySQL 数据必须持久化Volume数据库密码等配置通过环境变量注入敏感信息管理以及服务间通过 DNS 解析互相发现自定义网络。可以说掌握了 WordPress MySQL 的编排你就掌握了一般 Web 应用的编排范式。二、Compose 文件完整配置2.1 目录结构wordpress/ ├── docker-compose.yml ├── .env# 环境变量不提交到 Git└── .gitignore2.2 docker-compose.ymlservices: 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}:80environment: -WORDPRESS_DB_HOSTdb -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: bridge2.3 .env 文件MYSQL_ROOT_PASSWORDChangeMeRoot123!MYSQL_DATABASEwordpressMYSQL_USERwpuserMYSQL_PASSWORDChangeMeUser456!WORDPRESS_PORT8080安全警告以上密码仅为示例。在生产环境中请使用强随机密码不要将.env提交到版本控制系统可考虑使用 Docker SecretsSwarm 模式或 Kubernetes Secrets 来管理。这里.env文件必须加入.gitignore否则密码会被提交到 Git 历史。三、关键配置解析3.1 数据库服务dbMySQL 容器使用了几个关键环境变量MYSQL_ROOT_PASSWORDMySQL 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_USER和MYSQL_PASSWORD对应。WORDPRESS_DB_NAME要使用的数据库名与MYSQL_DATABASE对应。WordPress 在启动时会自动检测WORDPRESS_DB_HOST指定的数据库是否可用。如果数据库不存在或凭证错误WordPress 会进入安装引导页面而不是正常运行。因此depends_onservice_healthy确保了它启动时 MySQL 已经接受连接。3.3 启动顺序depends_on service_healthy第 15 篇讲过的知识点在此完美落地depends_on: db: condition: service_healthyCompose 会先启动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 ✔ Volumewordpress_db-dataCreated0.0s ✔ Volumewordpress_wp-dataCreated0.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 和 .envdockercompose up-d# 5. 检查日志dockercompose logs wordpress|grepcomplete# 不会出现安装向导直接可以访问访问http://localhost:8080你之前写的测试文章仍然存在。数据卷确保了数据在容器销毁后不会丢失。五、常见踩坑与解决坑 1MySQL 启动后 WordPress 连接报错现象WordPress 显示“建立数据库连接时出错”。排查# 查看 WordPress 日志dockercompose logs wordpress# 检查环境变量是否正确注入dockercomposeexecwordpressenv|grepWORDPRESS_DB# 确认 MySQL 确实在运行且健康dockercomposeexecdb mysqladminping-hlocalhost-uroot -p${MYSQL_ROOT_PASSWORD}常见原因.env文件未放置在正确位置必须与docker-compose.yml同级或MYSQL_PASSWORD与WORDPRESS_DB_PASSWORD不一致。坑 2WordPress 首次启动卡在安装向导这是正常行为WordPress 镜像并不会自动完成安装向导设置站点标题、管理员账号等。你需要通过浏览器访问http://localhost:8080手动完成。完成安装后WordPress 会在数据库中写入站点配置之后重启容器不会再出现安装向导。坑 3端口冲突现象启动时提示Bind for 0.0.0.0:8080 failed: port is already allocated。解决修改.env中的WORDPRESS_PORT8081或在启动时覆盖WORDPRESS_PORT8081dockercompose 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_onservice_healthy彻底解决了“数据库未就绪导致应用崩溃”的问题。配置管理通过.env文件统一管理环境变量和敏感信息避免硬编码。健康检查MySQL 用mysqladmin pingWordPress 用 HTTP 端点验证确保服务真正可用。下一篇——第 17 篇Compose 进阶多 Compose 文件与环境覆盖我们将学习如何通过多文件组合和环境特定覆盖文件让同一套 Compose 配置适配开发、测试、生产等多套环境真正实现“一次编写到处部署”。想了解更多还可以去各个平台搜索「IT策士」一起升级 IT 思维
第16篇 实战:用 Docker Compose 编排 WordPress 与 MySQL
发布时间:2026/5/30 1:59:46
IT策士 10余年一线大厂经验专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章助你少走弯路。到目前为止我们的贯穿案例一直是 Flask Redis 计数器。它足够经典但有些读者可能会觉得“太轻量”了——毕竟只有两个服务依赖关系也很简单。在实际工作中你编排的应用栈往往更复杂有前端有数据库数据库还需要初始化 root 密码Web 服务器必须等待数据库完全就绪才能连接。今天我们就来编排一个更真实的应用栈——WordPress MySQL。这个案例涉及到了完整的环境变量管理、启动顺序控制、数据持久化以及一个你在生产环境中必然会遇到的问题数据库密码等敏感信息该如何处理。通过这个实战你将看到前几篇学到的概念是如何在一个更复杂的场景中串联起来的。一、为什么选 WordPress MySQLWordPress 是全球使用最广泛的内容管理系统它由两个核心组件构成WordPressPHP 编写的 Web 应用处理前端请求MySQL关系型数据库存储文章、用户、配置等数据这个组合是 Compose 教学中的经典案例因为它天然涵盖了我们在第 11-15 篇学到的所有关键概念WordPress 依赖 MySQL启动顺序控制MySQL 数据必须持久化Volume数据库密码等配置通过环境变量注入敏感信息管理以及服务间通过 DNS 解析互相发现自定义网络。可以说掌握了 WordPress MySQL 的编排你就掌握了一般 Web 应用的编排范式。二、Compose 文件完整配置2.1 目录结构wordpress/ ├── docker-compose.yml ├── .env# 环境变量不提交到 Git└── .gitignore2.2 docker-compose.ymlservices: 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}:80environment: -WORDPRESS_DB_HOSTdb -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: bridge2.3 .env 文件MYSQL_ROOT_PASSWORDChangeMeRoot123!MYSQL_DATABASEwordpressMYSQL_USERwpuserMYSQL_PASSWORDChangeMeUser456!WORDPRESS_PORT8080安全警告以上密码仅为示例。在生产环境中请使用强随机密码不要将.env提交到版本控制系统可考虑使用 Docker SecretsSwarm 模式或 Kubernetes Secrets 来管理。这里.env文件必须加入.gitignore否则密码会被提交到 Git 历史。三、关键配置解析3.1 数据库服务dbMySQL 容器使用了几个关键环境变量MYSQL_ROOT_PASSWORDMySQL 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_USER和MYSQL_PASSWORD对应。WORDPRESS_DB_NAME要使用的数据库名与MYSQL_DATABASE对应。WordPress 在启动时会自动检测WORDPRESS_DB_HOST指定的数据库是否可用。如果数据库不存在或凭证错误WordPress 会进入安装引导页面而不是正常运行。因此depends_onservice_healthy确保了它启动时 MySQL 已经接受连接。3.3 启动顺序depends_on service_healthy第 15 篇讲过的知识点在此完美落地depends_on: db: condition: service_healthyCompose 会先启动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 ✔ Volumewordpress_db-dataCreated0.0s ✔ Volumewordpress_wp-dataCreated0.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 和 .envdockercompose up-d# 5. 检查日志dockercompose logs wordpress|grepcomplete# 不会出现安装向导直接可以访问访问http://localhost:8080你之前写的测试文章仍然存在。数据卷确保了数据在容器销毁后不会丢失。五、常见踩坑与解决坑 1MySQL 启动后 WordPress 连接报错现象WordPress 显示“建立数据库连接时出错”。排查# 查看 WordPress 日志dockercompose logs wordpress# 检查环境变量是否正确注入dockercomposeexecwordpressenv|grepWORDPRESS_DB# 确认 MySQL 确实在运行且健康dockercomposeexecdb mysqladminping-hlocalhost-uroot -p${MYSQL_ROOT_PASSWORD}常见原因.env文件未放置在正确位置必须与docker-compose.yml同级或MYSQL_PASSWORD与WORDPRESS_DB_PASSWORD不一致。坑 2WordPress 首次启动卡在安装向导这是正常行为WordPress 镜像并不会自动完成安装向导设置站点标题、管理员账号等。你需要通过浏览器访问http://localhost:8080手动完成。完成安装后WordPress 会在数据库中写入站点配置之后重启容器不会再出现安装向导。坑 3端口冲突现象启动时提示Bind for 0.0.0.0:8080 failed: port is already allocated。解决修改.env中的WORDPRESS_PORT8081或在启动时覆盖WORDPRESS_PORT8081dockercompose 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_onservice_healthy彻底解决了“数据库未就绪导致应用崩溃”的问题。配置管理通过.env文件统一管理环境变量和敏感信息避免硬编码。健康检查MySQL 用mysqladmin pingWordPress 用 HTTP 端点验证确保服务真正可用。下一篇——第 17 篇Compose 进阶多 Compose 文件与环境覆盖我们将学习如何通过多文件组合和环境特定覆盖文件让同一套 Compose 配置适配开发、测试、生产等多套环境真正实现“一次编写到处部署”。想了解更多还可以去各个平台搜索「IT策士」一起升级 IT 思维