群晖 DSM 的 Container Manager(原 Docker 套件)有一个容易误解的地方:Healthcheck 检测失败,并不会自动触发容器重启。
这通常不是群晖的 Bug,而是 Docker 本身的机制。
一、为什么 Healthcheck 失败不重启?
Docker 将容器运行状态和健康状态分开管理:
| 容器状态 | Healthcheck 状态 | 是否自动重启 |
|---|---|---|
| Running | healthy | 否,正常运行 |
| Running | unhealthy | 不会自动重启 |
| Exited | — | 根据重启策略决定 |
| Running | starting | 不会自动重启 |
即使你配置了:
services:
myapp:
image: nginx:latest
restart: always
healthcheck:
test: ["CMD", "curl", "-f", "http://127.0.0.1:80/"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
当连续 3 次健康检查失败,容器只会被标记为 unhealthy,并不会退出或重启。
原因是:
healthcheck负责检测应用是否健康。restart: always负责容器主进程退出后的自动重启。- Docker Engine 默认不会把
unhealthy视为容器退出。
因此,即使在群晖 Container Manager 中启用了自动重新启动,也无法解决这个问题。
二、推荐解决方案:部署 Autoheal
可以在群晖 Container Manager 中额外部署一个 Autoheal 容器,专门监控其他容器的健康状态。
1. 在群晖中创建项目
打开 Container Manager → 项目 → 新增项目,使用以下 Docker Compose:
services:
autoheal:
image: willfarrell/autoheal:latest
container_name: autoheal
restart: always
network_mode: none
environment:
AUTOHEAL_CONTAINER_LABEL: all
AUTOHEAL_INTERVAL: 10
AUTOHEAL_START_PERIOD: 30
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /etc/localtime:/etc/localtime:ro
参数说明:
| 参数 | 作用 |
|---|---|
AUTOHEAL_CONTAINER_LABEL=all | 监控所有容器 |
AUTOHEAL_INTERVAL=10 | 每 10 秒检查一次健康状态 |
AUTOHEAL_START_PERIOD=30 | Autoheal 启动后等待 30 秒 |
restart: always | Autoheal 自身退出后自动重启 |
docker.sock | 允许 Autoheal 操作 Docker 容器 |
2. 只监控指定容器(更推荐)
如果你的群晖运行了多个容器,我更建议只针对关键业务容器开启自动恢复,避免其他容器因短暂异常被误重启。
例如:
services:
myapp:
image: nginx:latest
restart: unless-stopped
labels:
autoheal: "true"
healthcheck:
test:
- CMD-SHELL
- "wget -q --spider http://127.0.0.1:80/ || exit 1"
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
autoheal:
image: willfarrell/autoheal:latest
container_name: autoheal
restart: always
network_mode: none
environment:
AUTOHEAL_CONTAINER_LABEL: autoheal
AUTOHEAL_INTERVAL: 10
volumes:
- /var/run/docker.sock:/var/run/docker.sock
这里使用 wget 检测,前提是目标镜像内包含该命令。