15.8.3 服务定义与依赖编排(depends_on、healthcheck)
本节聚焦 Compose 中服务定义与依赖编排,核心在于明确服务启动顺序、健康状态与可用性保障。通过 depends_on 管理依赖关系,通过 healthcheck 判断服务是否真正就绪,避免上游服务因下游未就绪而启动失败或异常。
原理草图:依赖与健康检查流程#
1. 服务定义关键字段与最小可运行示例#
以下示例演示 MySQL + Redis + 应用 + Nginx 的依赖编排,含健康检查与启动顺序控制。
文件: ./compose/docker-compose.yml
version: "3.9"
services:
db:
image: mysql:8.0
container_name: demo-db
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: appdb
ports:
- "3306:3306"
volumes:
- dbdata:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-prootpass"]
interval: 10s
timeout: 5s
retries: 5
start_period: 20s
restart: unless-stopped
redis:
image: redis:7
container_name: demo-redis
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 5
restart: unless-stopped
app:
image: nginx:1.25
container_name: demo-app
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
ports:
- "8080:80"
environment:
APP_ENV: "prod"
restart: on-failure
nginx:
image: nginx:1.25
container_name: demo-nginx
depends_on:
app:
condition: service_started
ports:
- "80:80"
restart: unless-stopped
volumes:
dbdata:
启动命令与预期效果
# 进入目录
cd ./compose
# 启动
docker compose up -d
# 预期:db/redis 先启动并通过 healthcheck,app 随后启动
docker compose ps
2. depends_on 语义与健康依赖#
service_started:仅保证容器进程启动service_healthy:要求 healthcheck 通过后再启动依赖服务
注意:condition需要 Compose 版本支持(docker compose v2+)。
验证依赖状态
# 查看服务健康状态
docker inspect -f '{{.State.Health.Status}}' demo-db
docker inspect -f '{{.State.Health.Status}}' demo-redis
# 预期:healthy
3. healthcheck 设计与命令解释#
健康检查应轻量、稳定、低副作用,避免复杂 SQL 或长耗时操作。
典型命令解释
- mysqladmin ping:检查 MySQL 是否接受连接
- redis-cli ping:检查 Redis 是否可响应
- curl -f:HTTP 健康探针,非 2xx 退出码
示例:应用健康检查
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost/health || exit 1"]
interval: 10s
timeout: 3s
retries: 3
start_period: 15s
4. 常用命令清单(含解释)#
# 查看 compose 版本
docker compose version
# 查看配置解析结果(排错用)
docker compose config
# 查看容器日志
docker compose logs -f app
# 查看健康状态变更
docker events --filter 'event=health_status'
5. 排错场景与定位方法#
问题1:app 仍然先于 db 启动
- 检查 depends_on 是否包含 condition: service_healthy
- 确认 db 容器存在 healthcheck
docker compose config | grep -A5 depends_on
问题2:db 一直 unhealthy
- 容器内命令是否可用(mysqladmin 是否存在)
- 密码或连接地址是否正确
docker exec -it demo-db mysqladmin ping -h 127.0.0.1 -prootpass
问题3:healthcheck 过重导致性能抖动
- 缩短探针逻辑,减少频率
- 对数据库使用轻量 ping 而非复杂 SQL
6. 练习#
- 为
app增加healthcheck,并让nginx依赖app的service_healthy。 - 将
redis的interval改为5s,观察健康状态变化频率。 - 故意配置错误的
MYSQL_ROOT_PASSWORD,观察db状态并修复。
7. 小结#
合理设置 depends_on 与 healthcheck,可显著提高多容器应用启动稳定性与可用性。生产实践中仍需结合应用层重试、熔断与监控告警,避免单点依赖判定失效。