Administrator
Administrator
发布于 2026-10-28 / 0 阅读
0
0

Docker 故障排查(06):容器显示 Up,网站却访问不了:沿请求路径逐层检查

适用:使用 systemd 的 Linux 服务器、常规 rootful Docker Engine;Compose 示例使用 docker compose V2。本文为教学故障场景,错误文本和结果为示意,具体输出以现场为准。

一、遭遇情况:docker ps 正常,curl 却失败

Web 容器一直显示 Up,端口栏也有映射,但访问服务器端口时连接被重置、拒绝或超时。只盯着 docker ps 看,通常找不出原因。

本篇案例是 Python Web 服务在容器里只监听 127.0.0.1:8000。进程运行正常,容器自己访问成功,但发布端口转发到容器网络接口时,目标地址并没有服务监听。

二、原因分析:不同空间里的 127.0.0.1 不是同一处

容器内的 127.0.0.1 指容器自己的回环接口,不是宿主机。应用绑定它,通常只能从该容器内部访问。为了通过容器网络接口接收请求,应用通常需要监听 0.0.0.0 或合适的容器地址。

另一个容易混淆的地方是 -p 127.0.0.1:18086:8000:这里的回环绑定发生在宿主机一侧,适合只让本机反向代理访问。它与容器内应用的绑定地址是两层独立设置。

从应用到远程访问的请求路径

三、排查思路:从里到外缩小故障范围

1. 容器是否真的在运行,应用是否报错

假设业务容器名为 web:

docker inspect web --format 'Status={{.State.Status}} Error={{.State.Error}}'
docker logs --tail 100 --timestamps web
docker port web
docker inspect web --format '{{json .NetworkSettings.Ports}}'

Up 只说明主进程尚在运行。应用可能没有启动监听、还在初始化,或者错误地监听了其他端口。Dockerfile 的 EXPOSE 是端口说明,不等于已经执行宿主机端口发布。

2. 容器内能访问,宿主机能访问吗

有合适客户端工具时,从容器内请求应用;镜像很精简而没有 curl、ss 时,不必因此断言网络坏了,更不要为了排查直接修改生产镜像安装一堆工具。

宿主机使用 curl --connect-timeout 3 --max-time 5 http://127.0.0.1:发布端口。如果本机成功而远程失败,才继续查外部访问路径;如果本机就失败,先处理应用和映射。

四、实践:复现“容器内可访问,发布端口失败”

以下使用独立实验名和本机练习端口,前提是镜像可拉取:

docker run -d --name dt06-loop -p 127.0.0.1:18086:8000 python:3.12-alpine python -m http.server 8000 --bind 127.0.0.1
docker logs --tail 20 dt06-loop
docker exec dt06-loop python -c 'import urllib.request; print(urllib.request.urlopen("http://127.0.0.1:8000", timeout=3).status)'
curl -I --connect-timeout 3 --max-time 5 http://127.0.0.1:18086

容器内部的 Python 请求应返回 200,宿主机请求预期失败。具体失败文本取决于网络实现,判断重点是同一服务从不同入口的可达性不同。

只对这个明确的实验容器停止、删除并修正绑定:

docker stop dt06-loop
docker rm dt06-loop
docker run -d --name dt06-loop -p 127.0.0.1:18086:8000 python:3.12-alpine python -m http.server 8000 --bind 0.0.0.0
curl -I --connect-timeout 3 --max-time 5 http://127.0.0.1:18086

此时宿主机应得到 HTTP 响应。练习仍只发布到宿主机回环地址,因此另一台机器直接访问服务器的 18086 失败仍然符合配置预期。

五、本机正常、外部不通时查哪里

先明确部署方案。如果入口由宿主机 Nginx 反向代理,后端只发布到 127.0.0.1 是合理设计,外部应访问代理的业务端口。不要为了测试方便把所有后端端口公开。

如果业务确实需要直接远程访问,则要确认发布地址包含正确的服务器接口、云安全组允许预期来源、宿主机转发与防火墙规则匹配。云服务器公网 IP 可能通过平台 NAT 映射,不一定能在本机直接绑定该公网地址。

检查时可读取 sudo nft list ruleset 或适合本系统后端的 sudo iptables -S,但不要同时盲改两套规则。Docker 的端口发布会参与防火墙与转发处理,不能只凭 ufw status 里一条普通 INPUT 规则判断整个链路。

curl 已收到 403、404、502 等 HTTP 状态时,至少说明某个 HTTP 服务作出了响应,应转向对应应用或代理层,不要继续当成单纯 TCP 不通。

六、验证与总结

至少验证三个视角:容器内请求、宿主机发布入口请求、预期客户端真实入口请求。记录哪一步开始失败,证据会自然指向应用监听、发布映射或外部链路。

这类故障的核心是把“进程活着”“端口可达”“HTTP 正确”“业务可用”分开验证。修复容器内监听地址后,还要确认宿主机入口的暴露范围符合原部署设计。

参考资料


上一篇 · 系列目录 · 下一篇


评论