Docker 容器显示 healthy,网站却打不开?健康检查、端口映射与反向代理排查

Docker 容器显示 healthy,并不代表网站的外部访问链路正常。本文沿容器内部、宿主机映射端口、反向代理与公网入口逐段排查,说明监听地址、EXPOSE、Compose 端口重建和代理网络的区别,并给出配置备份、回退与恢复验收要求,避免盲目重启、清空防火墙或删除数据卷。
Docker 容器显示 healthy,网站却打不开?健康检查、端口映射与反向代理排查

docker ps 显示容器是 healthy,浏览器却超时,或者反向代理返回 502。这两种现象完全可以同时出现:Docker 的健康状态取决于配置的检查命令,它可能只访问容器内部的 localhost,没有经过宿主机端口、防火墙、反向代理或公网入口。

排查时需要把访问路径拆开验证。本文适用于 Linux Docker Engine 与 Docker Compose 的普通 Web 服务,示例为容器内 HTTP 8080、宿主机回环地址 18080。服务名、容器名和域名均需替换。host 网络、Swarm、Kubernetes、Docker Desktop 和 rootless 模式的网络路径有差异,不能直接照搬所有结论。

healthy 到底证明了哪一段正常

HEALTHCHECK 在容器中运行检查命令,退出码决定健康检查结果。命令执行成功只能证明它所检查的条件成立。[1]

例如,检查 http://127.0.0.1:8080/health 返回成功,无法证明应用监听了容器网卡,也无法证明域名指向正确入口。若脚本只检查进程存在,甚至没有测试 HTTP 请求。

先保存当前状态和近期日志:

docker ps --filter name=web
docker inspect --format '{{json .Config.Healthcheck}}' web
docker inspect --format '{{json .State.Health}}' web
docker logs --since 15m --tail 200 web

这里的 web 是容器名示例。Compose 服务名可能与实际容器名不同,可先用 docker compose ps 确认。健康检查输出和应用日志可能含内部地址或敏感信息,分享前应脱敏,不要公开完整 inspect 结果。

检查脚本是否存在以下问题:请求失败后被 || true 吞掉;只做 TCP 探测;curl 没有按预期处理 HTTP 错误;只检查静态路径而业务依赖不可用;检查输出被无条件成功的最后一条命令覆盖。调整前应理解返回码,不要把所有非 200 响应简单归为故障,某些健康端点可能约定返回 204。

按容器、宿主机、代理、公网逐段缩小范围

验证位置 要回答的问题 失败时重点检查
容器内部 应用是否能响应,监听地址是什么 进程、端口、协议、健康检查脚本
宿主机映射端口 发布端口能否到达容器 映射关系、绑定地址、Docker 网络
反向代理所在环境 代理能否访问正确上游 容器 DNS、网络、上游端口、协议
外部客户端 域名与公网入口是否连通 DNS、IPv4/IPv6、安全组、CDN、TLS

建议记录各层的时间、状态码和报错,而非只写“访问失败”。连接拒绝、超时、TLS 握手失败与 HTTP 502 的排查路径不同。外部出现 502 说明某个网关已返回响应,不代表请求已到你的目标容器。

容器内能访问 localhost,仍要检查监听地址

如果镜像已经包含 curl,可以执行:

docker exec web curl --connect-timeout 3 --max-time 5 -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/health

精简镜像可能没有 curl 或 Shell。这时使用镜像已有的诊断工具,或经审批的临时调试容器;不要在生产容器中随意安装工具并把临时变更当成修复。

若容器已有 ss,可查看监听:

docker exec web ss -lnt

应用只监听容器内的 127.0.0.1:8080 时,内部检查能通过,普通 bridge 网络经容器网卡进入的请求却无法交给它。通常需要按应用自身配置监听 0.0.0.0:8080,同时确认 IPv6 监听与实际网络相匹配。

应用监听所有容器接口与宿主机发布公网端口是两个不同设置。前者修复容器内可达性,后者决定外部入口暴露范围;不要为了修复前者顺手把管理接口发布到公网。

检查发布端口,EXPOSE 不会自动建立入口

查看实际映射,而非只看 Dockerfile:

docker port web
docker inspect --format '{{json .NetworkSettings.Ports}}' web
docker compose ps

EXPOSE 8080 属于镜像声明,不会自动把宿主机 8080 发布给外部。普通 bridge 网络需要通过 ports 或 -p 建立相应入口。[2]

如果 Nginx 运行在同一宿主机上,可以考虑仅向回环地址发布:

services:
  web:
    image: your-approved-image:your-pinned-tag
    ports:
      - "127.0.0.1:18080:8080"

该片段只示范端口关系,不能替换原有完整 Compose 文件。保留卷、环境变量、网络、运行用户等配置。Docker 官方还提示,28.0.0 以前版本对回环地址发布存在同二层网络可达的历史问题;安全边界应结合实际 Engine 版本与网络策略评估。[2]

修改前备份 Compose 文件,记录当前镜像版本、卷和配置。在正确项目目录检查配置,再按维护计划重建目标服务:

docker compose config --quiet
docker compose up -d --no-deps web
curl --connect-timeout 3 --max-time 5 -v http://127.0.0.1:18080/health

重建可能造成短暂中断。不要使用 down -v,也不要通过删除卷解决端口问题。restart 不会把修改后的端口映射重新应用到已有容器。回退时恢复已备份配置和原镜像版本,再重建服务;有数据库迁移时还需单独评估数据兼容性。

Docker 发布端口与宿主机防火墙交互涉及 Docker 自身规则,不应只凭一条 UFW 状态判断公网暴露情况。不要清空 iptables/nftables 规则试错,应结合官方网络文档、现有策略与实际外部测试定位。

反向代理也在容器中时,localhost 通常指错地方

Nginx 如果也是一个容器,其 127.0.0.1 指向 Nginx 自己,并不指向 Web 容器,也不自动指向宿主机。

两个服务位于同一个 Compose 网络时,常见上游写法是服务名加容器端口,例如:

location / {
    proxy_pass http://web:8080;
}

这里使用 8080,而非宿主机发布的 18080。服务名能否解析取决于两者是否处于共享网络、服务名称和网络别名;不同 Compose 项目不会自动共享默认网络。

应从代理所在容器或等效网络环境测试上游,宿主机 curl 成功不能证明代理容器也能访问。上游若使用 HTTPS,还需检查协议、证书校验与 SNI;不要把 HTTP 与 HTTPS 错配当成端口未开放。

应用容器重建可能改变地址。若 Nginx 仍使用旧解析结果,应根据当前 Nginx 版本和上游配置处理 DNS 更新,并在语法检查通过后安全重载,不能把容器 IP 写死作为长期方案。代理配置改动也应保留备份;不要为排错关闭上游证书验证。

宿主机通了,公网仍不通时看入口层

确认代理到上游成功后,再从独立客户端检查:

  • 域名 A、AAAA 记录是否指向当前入口,IPv6 路径是否同样可用。
  • 云安全组、宿主机策略和负载均衡是否允许必要的入口端口。
  • 代理是否监听预期地址,TLS 证书是否匹配域名。
  • CDN 与负载均衡使用的回源协议、端口、Host 和健康检查路径是否正确。

如果入口直接由源站终止该域名的 HTTPS,可用下面的形式在不修改公共 DNS 的情况下测试指定地址:

# 192.0.2.10 是文档示例地址,替换为真实源站 IP
curl --connect-timeout 3 --max-time 10 -v --resolve example.com:443:192.0.2.10 https://example.com/health

该测试保留域名对应的 Host 与 TLS SNI,但不能绕过访问控制。源站若只接受 CDN 访问或采用私有回源证书,应在获授权的路径按既定信任配置测试,不要临时向所有来源开放,也不要加 -k 掩盖证书问题。

让健康检查与业务验收各司其职

容器内检查适合验证本地进程和必要依赖,入口监测则需要经过反向代理与实际访问链路。健康端点应轻量、无副作用,避免写数据库、发邮件或触发耗时业务。

Compose 的 start_period、interval、timeout 和 retries 应匹配应用启动与响应特征。[3] 延长宽限期可以减少初始化阶段的误报,却不能修复端口错误或错误上游。普通 Docker Engine 的重启策略主要基于进程退出行为,仅变为 unhealthy 不会自动触发重启;不要期待它自行修好外部访问。

恢复完成至少确认:容器检查稳定、代理所在环境能访问上游、真实域名入口能返回预期内容,并验证登录或关键只读业务。记录改动后持续观察日志,避免只拿到一次 200 就结束处理。最终应能指出故障发生在哪一段,以及哪些监测能够覆盖这一段。

参考资料

资料核验日期:2026 年 10 月 23 日。本文命令与配置均为示例,未声称已在读者生产环境实测。

  1. Dockerfile HEALTHCHECK:检查命令与健康状态
  2. Docker 端口发布:映射与安全边界
  3. Compose 服务 healthcheck 配置
Docker与容器

Docker 配了日志轮转却没生效?已有容器、Compose 重建与配置核验

2026-10-20 15:29:41

行业资讯

云市场周报 (2025.08.29):解读阿里云g8y、腾讯云Serverless容器与FinOps趋势

2025-8-29 10:03:26