1. 概述
Docker Compose 是一个用于部署、运行和维护多容器应用的工具。通过 compose 文件,我们可以定义多个协同工作的容器来构建完整的应用系统。Docker Compose 的一个实用功能是支持容器间的依赖关系定义,从而控制容器的启动顺序。
✅ 在本教程中,我们将学习 Docker Compose 中的服务依赖机制,并演示如何在包含 MySQL 容器的环境中使用它。
2. 容器的健康检查与就绪状态
健康检查(Health Check)是一种通过执行特定命令并检查响应结果,来判断系统是否正常运行的机制。具体来说,外部系统(称为 prober)会执行命令并根据返回结果判断系统是否健康。例如,对一个网站的健康检查可能包括发送一个 GET 请求,并期望返回 200 状态码。
在 Docker 中,定义健康检查可以为容器的生命周期增加一个新的维度。除了常见的 Created、Started、Stopped 状态之外,Docker 还能识别容器是否处于 Healthy 或 Unhealthy 状态。这种状态可用于更精细的控制,比如只在容器状态为 Healthy 时才路由流量到该容器。这对于启动时间较长的容器(如数据库)尤其有用。
2.1 在 Dockerfile 中定义健康检查
我们可以在构建镜像时通过 Dockerfile 的 HEALTHCHECK
指令来定义健康检查:
$ cat Dockerfile
FROM mysql:5.7
ENV MYSQL_ROOT_PASSWORD=example
HEALTHCHECK --interval=10s --timeout=5s --retries=5 CMD mysqladmin ping -h localhost || exit 1
2.2 在 docker-compose.yaml 中定义健康检查
也可以在 docker-compose.yaml
文件中通过 healthcheck
字段来指定健康检查命令:
services:
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: example
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
上述配置表示每 10 秒执行一次健康检查命令,每次执行等待 5 秒,连续失败 5 次后标记为不健康。
3. Docker Compose 服务依赖关系
对于多容器应用,容器之间可能存在依赖关系,要求它们按照特定顺序启动。例如,Web 应用容器可能在启动时执行数据库迁移脚本,这就要求数据库容器必须先就绪。
Docker Compose 提供了 depends_on
字段来定义服务之间的依赖关系。例如,如果 serviceA 需要在 serviceB 启动后才启动,可以在 serviceA 的配置中添加:
services:
serviceA:
image: alpine:latest
depends_on:
- serviceB
serviceB:
image: alpine:latest
启动时,Docker 会先创建并运行 serviceB,等其状态变为 Running 后再启动 serviceA。
⚠️ 注意:depends_on
控制的是容器的启动顺序,而不是就绪状态。
3.1 service_started
默认情况下,depends_on
的条件是 service_started
,即只要目标服务容器状态变为 Started,就认为依赖满足。
3.2 service_ready
如果使用 service_ready
条件,则 Docker 会等待目标服务不仅 Started,还要达到 Healthy 状态。这要求目标服务必须定义了 healthcheck
,否则 Docker 无法判断其是否就绪。
depends_on:
db:
condition: service_healthy
3.3 service_completed_successfully
service_completed_successfully
表示目标服务必须正常执行完毕(退出码为 0)。这通常用于前置初始化容器(如数据迁移容器),这类容器通常是短暂运行的。
4. MySQL 容器的就绪判断
MySQL 是一个广泛使用的开源关系型数据库管理系统。我们通常认为 MySQL 就绪的标准是它开始接受外部连接请求并能执行 SQL 命令。
✅ **判断 MySQL 是否就绪的一个简单方式是执行一个无副作用的 SQL 命令,如 SHOW DATABASES;
**:
$ mysql -u root -pexample --execute 'SHOW DATABASES;'
+--------------------+
| Database |
...
如果执行失败,通常表示数据库尚未就绪,此时健康检查失败;否则认为容器已就绪。
4.1 示例:容器启动依赖配置
我们来配置一个包含 web 和 db 两个服务的环境,其中 web 依赖 db 的就绪状态:
services:
web:
image: alpine:latest
depends_on:
db:
condition: service_healthy
db:
image: mysql:5.7
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
healthcheck:
test: ["CMD", "mysql", "-u", "root", "-proot", "--execute", "SHOW DATABASES;"]
interval: 3s
retries: 5
timeout: 5s
关键点:
- web 服务通过
depends_on
依赖 db,并指定service_healthy
条件。 - db 定义了健康检查命令,确保只有当 MySQL 真正就绪后,web 才会启动。
4.2 查看健康检查效果
运行以下命令启动服务:
$ docker compose up -d
输出如下:
[+] Running 1/3
✔ Network mysql-complete_default Created 0.0s
✔ Container mysql-complete-db-1 Created 0.1s
✔ Container mysql-complete-web-1 Created 0.1s
随后你会看到 db 容器先进入 Running 状态,然后进入 Waiting,等待健康检查通过:
[+] Running 2/3
✔ Network mysql-complete_default Created 0.0s
⠼ Container mysql-complete-db-1 Waiting 2.5s
✔ Container mysql-complete-web-1 Created 0.1s
一旦 db 容器通过健康检查,状态变为 Healthy,web 容器才会启动:
[+] Running 3/3
✔ Network mysql-complete_default Created 0.0s
✔ Container mysql-complete-db-1 Healthy 10.0s
✔ Container mysql-complete-web-1 Started 10.3s
5. 总结
本教程中我们学习了:
- Docker 容器健康检查的作用及配置方式
- Docker Compose 中服务依赖的使用方法
- 如何通过
depends_on
+healthcheck
实现容器启动顺序控制 - MySQL 容器就绪判断的最佳实践(如使用
SHOW DATABASES;
)
✅ 使用健康检查和依赖条件组合,可以有效避免容器因依赖服务未就绪而导致的启动失败问题。这是构建健壮容器化应用的重要一步。