## 为什么需要健康检查
你有没有遇到过这种情况:容器还在运行,但服务已经挂了?Nginx 返回 502,数据库连不上,应用卡死但不退出。Docker 只关心进程是否存活,不关心服务是否可用。
健康检查(Healthcheck)就是解决这个问题的。它让 Docker 定期探测服务状态,发现异常时可以自动重启。
## 基础用法
在 docker-compose.yml 中添加 healthcheck 配置:
```yaml
services:
web:
image: nginx:alpine
ports:
- "80:80"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
```
参数说明:
- `test`:健康检查命令,返回 0 表示健康
- `interval`:检查间隔,默认 30s
- `timeout`:单次检查超时时间
- `retries`:连续失败次数阈值,超过后容器被标记为 unhealthy
- `start_period`:容器启动后的宽限期,这段时间失败不计入 retries
## 常用服务的健康检查配置
**MySQL/MariaDB:**
```yaml
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
```
**PostgreSQL:**
```yaml
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
```
**Redis:**
```yaml
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
```
## 利用健康检查控制启动顺序
Docker Compose 的 `depends_on` 只保证启动顺序,不保证服务就绪。结合 `condition: service_healthy` 可以实现真正的按依赖启动:
```yaml
services:
db:
image: mysql:8
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
retries: 10
app:
depends_on:
db:
condition: service_healthy
```
这样 app 容器会等到 MySQL 真正可以接受连接后才启动。
## 实战建议
1. 不要用太复杂的检查命令,健康检查本身也有开销
2. timeout 不要设太大,避免健康检查本身卡死
3. 生产环境建议同时配合外部监控,Docker 健康检查是最后一道防线
配置好健康检查后,你的服务就能在半夜挂了的时候自动恢复,不用半夜爬起来重启容器了。