Docker Compose 容器显示 unhealthy 怎么排查?健康检查、依赖与安全重建

从健康检查输出、容器内部网络和启动依赖定位问题,避免误删数据卷

排查 Docker Compose 容器 unhealthy,读取健康检查输出,区分命令、容器网络、启动依赖和应用故障,并安全重建与回退。

先别重建容器:Docker Compose 显示容器 unhealthy,表示健康检查连续失败,不等于容器已经停止。先运行 docker compose ps、读取健康检查最近输出,再从容器内部执行同一条检查命令。常见原因是检查工具不存在、地址写成宿主机、启动时间不足、依赖服务尚未就绪,或应用真的无法响应。直接执行 docker compose down -v 会删除命名卷,可能造成数据库和上传数据丢失,排障时禁止使用。

查看状态和日志不收费,也不修改数据。重启、重新创建或更新镜像可能造成短时中断;容器可写层中的临时修改会在重建后丢失。操作前保存 compose.yaml、环境变量清单和卷挂载关系,确认数据库与上传目录位于持久卷,并记录当前镜像摘要。

先把失败的那一条健康检查读出来

在 Compose 项目目录执行:

docker compose ps
docker ps --filter health=unhealthy
docker inspect --format '{{json .State.Health}}' CONTAINER_NAME
docker compose logs --tail=200 SERVICE_NAME

把容器名和服务名替换为实际值。.State.Health.Log 会保留最近几次检查的退出码和输出,它比只看 unhealthy 更有用。若镜像根本没有定义健康检查,状态会是 none,此时问题可能来自 Compose 配置、上游负载均衡或应用监控,不要误判为 Docker 的健康状态。

检查命令为什么在宿主机成功,容器里却失败

健康检查在容器内部执行。宿主机安装了 curl,不代表精简镜像里也有;宿主机的 127.0.0.1 指向宿主机,容器内的 127.0.0.1 只指向该容器。先进入容器执行完全相同的命令:

docker compose exec SERVICE_NAME sh
# 在容器内执行 compose.yaml 里的 healthcheck.test

如果提示命令不存在,应在镜像构建阶段加入必要的轻量检查工具,或改用应用本身已有的命令。不要在运行中的容器临时安装后就宣布修复,因为重建后修改会消失。HTTP 检查还要确认应用监听在正确地址和端口;只监听另一个接口、要求 Host、TLS 或认证时,简单请求会失败。

健康检查参数怎样设置才不会误判

services:
  app:
    image: example/app:1.2.3
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 40s

start_period 给应用初始化时间,期间失败不会立即计入连续失败;interval 是检查间隔,timeout 是单次最大等待,retries 是进入不健康状态前允许的连续失败次数。不要只为变成绿色就把超时调到几分钟。健康接口应快速证明进程已经可以接收核心请求,但不要在每次检查中执行慢报表、外部支付调用或重型数据库查询。

depends_on 为什么没有等数据库真正可用

Compose 的短写法 depends_on: [db] 只保证依赖服务先启动,不保证数据库已经通过初始化并能接受连接。需要等待依赖健康时,给数据库定义可靠健康检查,并使用长写法:

services:
  web:
    depends_on:
      db:
        condition: service_healthy
  db:
    image: mysql:8.4
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1"]
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 30s

示例只展示结构,真实 MySQL 检查需要使用受控凭据或不泄露密码的方式,并验证该镜像包含命令。即使 Compose 等到数据库健康,应用仍应处理运行中的数据库重启和短暂网络错误;depends_on 不是持续故障转移机制。

常见失败怎样分流

健康日志含义处理
executable file not found镜像缺少检查命令修改镜像或使用现有工具,不在运行容器临时修补
connection refused进程未监听或端口错误查应用启动日志、监听地址和实际端口
超时应用阻塞、依赖慢或阈值过短先查应用、数据库、CPU/IO,再决定阈值
401/403健康路径被认证保护建立最小无敏感信息的内部健康入口
启动后短暂失败预热或迁移尚未完成设置合理 start_period,并把一次性迁移与启动解耦

容器是 healthy 但业务仍报错时,要继续检查端口映射、反向代理、真实域名、网络和应用功能。健康检查只能证明你定义的条件,不会自动覆盖登录、上传、队列和数据一致性。

怎样安全应用新配置并完成验证

  1. 运行 docker compose config 验证合并后的最终配置。
  2. 在测试环境或单个服务上使用固定镜像版本验证健康检查。
  3. 执行 docker compose up -d SERVICE_NAME,不要带 -v 删除卷。
  4. 观察从 startinghealthy 的完整周期和应用日志。
  5. 从反向代理或真实客户端访问核心功能,确认容器重建后数据仍在。

回退:更新后失败时,恢复旧 compose.yaml 和旧镜像摘要,再只重建受影响服务。不要在没有备份的数据库卷上执行 down -v、删除卷或更换挂载目录。Compose 基础部署可参考Docker Compose 生产部署;宝塔场景可参考宝塔 Docker Compose 排障;若容器由 systemd 反复拉起,可查看systemd 重启循环排查

官方依据

云服务器教程Vue、React 单页应用刷新后 404 怎么办?Nginx History 路由与 API 分流2026-09-13云服务器教程Docker 提示 pull access denied 怎么办?镜像名、仓库权限与登录排查2026-09-13云服务器教程MySQL 报 ERROR 1205 Lock wait timeout 怎么办?阻塞事务与安全止损2026-09-12

加入开发者交流社区

与全球开发者、运维和工作室一起交流技术、分享经验、配置、账号与最新优惠信息

  • 云平台使用交流
  • 资源优惠信息
  • 最新教程与资讯
  • 开发者经验分享
联系 Telegram 客服
加入开发者交流社区