在 Docker 环境中,应用明明已经启动,却可能出现容器之间无法访问、宿主机端口不通、域名解析失败等问题。要快速定位故障,关键不是反复重启容器,而是理解数据包如何经过网络命名空间、虚拟网卡、网桥、路由和端口转发。本文将从通信原理入手,梳理一套可直接执行的排查方法。🔍
一、Docker 容器网络的基本原理
Docker 容器通常拥有独立的网络命名空间,其中包含自己的网卡、IP 地址、路由表和端口。使用默认的 bridge 网络时,Docker 会在宿主机上创建软件网桥,并通过一对虚拟以太网设备连接容器与网桥。可以把它理解为:容器中的 eth0 是网线的一端,宿主机上的虚拟接口是另一端,而 Docker 网桥则充当虚拟交换机。
同一桥接网络内的容器可以直接通信,但不同 Docker 网络默认相互隔离。容器访问外部网络时,数据包通常经过宿主机的地址伪装规则转换,外部设备看到的是宿主机地址,而不是容器内部地址。相关行为可参考 Docker Bridge 官方文档。
常见网络驱动
- bridge:适合单机上的大多数容器,是最常见的网络模式。
- host:容器直接使用宿主机网络栈,减少网络隔离,但也更容易产生端口冲突。
- overlay:用于跨宿主机的容器通信,常见于 Docker Swarm 等场景。
- macvlan:为容器分配独立的二层网络身份,适合需要直接接入物理局域网的服务。
- none:不为容器配置外部网络,适合强调隔离的任务。
二、容器之间如何通信
建议为同一应用栈创建用户自定义 bridge 网络,而不是长期依赖默认 bridge。自定义网络支持容器名称和网络别名解析,隔离边界也更加清晰。例如,前端容器可以通过 db:5432 访问名为 db 的数据库容器,不必写死容易变化的容器 IP。
需要特别注意,容器中的 127.0.0.1 只代表当前容器自身,并不指向宿主机或其他容器。应用若要接受来自其他容器的连接,通常应监听 0.0.0.0 或容器实际网卡地址。如果服务只绑定在 127.0.0.1,即使两个容器处于同一网络,也可能无法访问。⚠️
判断容器互通时,应使用“目标容器名称加容器内部端口”,不要误用宿主机映射端口,也不要把 localhost 当作其他服务。
三、端口发布为什么会失效
端口发布用于把宿主机端口转发到容器端口。例如 8080:80 表示访问宿主机的 8080 端口时,流量会转发到容器的 80 端口。它不会改变容器内应用实际监听的端口,也不等于应用一定能够响应请求。
排查端口问题时,可先执行:
docker ps
确认端口映射是否存在;再执行:
docker port 容器名
检查具体绑定关系。随后进入容器查看监听状态,例如使用:
ss -lntp
如果程序只监听 127.0.0.1:80,而不是 0.0.0.0:80,宿主机转发进来的请求通常无法到达应用。
还要检查宿主机端口是否被其他进程占用,以及防火墙或云平台安全规则是否允许访问。若映射形式为 127.0.0.1:8080:80,该端口通常只供宿主机本地访问;若绑定宿主机全部接口,暴露范围更大,应结合防火墙和业务需求谨慎配置。🛡️
四、常见故障与定位方法
1. 容器名称无法解析
先执行 docker network inspect 网络名,确认通信双方是否连接到同一个用户自定义网络。若通过 IP 可以访问、通过名称不行,应重点检查网络类型、服务名称和别名。必要时查看容器内的 /etc/resolv.conf,但不建议通过手工修改 hosts 文件长期维护容器地址。
2. 容器可以联网,但访问不到指定服务
可按照“DNS、路由、端口、应用”顺序逐层测试。先解析目标名称,再检查 ip route,随后使用 curl -v 目标地址 或 nc -vz 主机 端口 验证连接。能解析但连接被拒绝,通常说明目标端口未监听;长时间超时则更可能与路由、防火墙或网络隔离有关。
3. 宿主机能访问,其他设备不能访问
首先确认端口是否仅绑定在 127.0.0.1,其次检查宿主机防火墙、云安全组和上级路由设备。还要确认客户端访问的是宿主机可达地址,而不是容器内部私有 IP。容器 IP 通常只在 Docker 网络或宿主机内部有意义,不应直接作为外部访问入口。
4. 修改网络后配置没有生效
先用 docker inspect 容器名核实容器实际网络配置,不要仅根据 Compose 文件推断运行状态。部分网络和端口配置需要重新创建容器才能完整生效,可使用 docker compose up -d --force-recreate。执行前应确认数据卷和持久化策略,避免误删业务数据。
五、推荐的标准排查顺序
- 执行 docker ps,确认容器状态、健康检查结果和端口映射。
- 执行 docker logs 容器名,检查应用是否启动失败或监听了错误端口。
- 执行 docker inspect 容器名,核实 IP、网络、网关和端口配置。
- 执行 docker network inspect 网络名,确认通信双方是否处于正确网络。
- 在容器内部检查名称解析、路由表、监听端口和目标连通性。
- 最后检查宿主机防火墙、转发规则、端口占用及外部安全策略。
总结
Docker 网络故障看似复杂,本质上通常集中在四个边界:容器自身、容器网络、宿主机端口转发和外部访问链路。排查时应坚持从应用监听状态开始,再检查名称解析、网络归属、路由、端口映射和防火墙,避免一上来就删除网络或重装 Docker。✅
在日常部署中,优先使用用户自定义网络,通过服务名称通信,避免写死容器 IP;只发布真正需要对外开放的端口,并明确区分容器端口与宿主机端口。建立这种分层排查思路后,大多数容器网络问题都能被快速缩小范围并准确解决。