Docker 容器与宿主机网络互通:bridge 模式与常见排查
前言
在日常开发中,我们经常需要让容器和宿主机、容器和容器之间互相通信。Docker 默认使用 bridge 网络模式,理解它的工作原理,是排查"容器访问不了宿主机""宿主机访问不了容器端口"这类问题的基础。本文从 bridge 模式的结构讲起,再整理一套常见的排查步骤。内容以通用原理和官方文档中的常见命令为主。
一、bridge 模式的基本结构
Docker 安装后,会在宿主机上创建一个名为 docker0 的虚拟网桥,默认网段通常是 172.17.0.0/16。每启动一个使用默认 bridge 网络的容器,Docker 会做这几件事:
- 创建一对 veth 虚拟网卡,一端放进容器的网络命名空间(显示为 eth0),另一端挂在 docker0 网桥上;
- 从网段中给容器分配一个 IP,网关指向 docker0 的地址(如 172.17.0.1);
- 通过 iptables 规则实现地址转换(NAT)和端口映射。
可以用下面的命令查看相关信息:
# 查看网络列表和 bridge 网络详情
docker network ls
docker network inspect bridge
# 查看宿主机上的网桥和 veth 接口
ip addr show docker0
ip link | grep veth
二、容器与宿主机如何互通
1. 宿主机访问容器
宿主机可以直接通过容器 IP 访问容器内的服务,因为 docker0 网桥就在宿主机上。更常见的做法是使用端口映射:
docker run -d --name web -p 8080:80 nginx
curl http://127.0.0.1:8080
-p 8080:80 会让 Docker 添加 DNAT 规则,把访问宿主机 8080 端口的流量转发到容器的 80 端口。
2. 容器访问宿主机
容器访问外部网络时,流量经过 docker0,再由宿主机做 SNAT(MASQUERADE)后发出。容器访问宿主机本身,可以使用 docker0 网关地址(默认 172.17.0.1)。需要注意:宿主机上的服务必须监听在 0.0.0.0 或 docker0 地址上,如果只监听 127.0.0.1,容器是访问不到的。
在 Linux 上,较新版本的 Docker 支持通过 --add-host=host.docker.internal:host-gateway 让容器用域名访问宿主机:
docker run --rm --add-host=host.docker.internal:host-gateway busybox ping -c 2 host.docker.internal
3. 容器之间互通
默认 bridge 网络上的容器可以通过 IP 互相访问,但不支持通过容器名解析。如果希望用容器名互访,建议创建自定义 bridge 网络,它自带内嵌 DNS:
docker network create mynet
docker run -d --name db --network mynet redis
docker run --rm --network mynet busybox ping -c 2 db
三、常见问题与排查步骤
问题 1:宿主机访问映射端口不通
- 确认容器在运行:
docker ps,查看 PORTS 列是否有映射; - 确认容器内的服务监听的是 0.0.0.0 而不是 127.0.0.1(容器内监听 127.0.0.1 时,映射端口无法访问);
- 查看宿主机端口监听情况:
ss -lntp | grep 8080; - 检查 NAT 规则:
iptables -t nat -nL DOCKER。
问题 2:容器访问不了外网
- 确认宿主机开启了 IP 转发:
sysctl net.ipv4.ip_forward,值应为 1; - 检查 POSTROUTING 链是否有 MASQUERADE 规则:
iptables -t nat -nL POSTROUTING; - 检查容器内 DNS 配置:
docker exec 容器名 cat /etc/resolv.conf,必要时在 run 时通过--dns指定; - 检查宿主机防火墙(如 firewalld、ufw)是否干扰了 Docker 的规则。
问题 3:容器访问不了宿主机上的服务
- 确认宿主机服务监听地址不是仅 127.0.0.1;
- 确认防火墙放行了来自 docker0 网段的访问;
- 用
docker exec进入容器,使用ping、curl或nc测试网关地址和目标端口,逐段缩小范围。
问题 4:网段冲突
如果 docker0 的默认网段与公司内网或 VPN 网段重叠,会出现部分地址不通。可以在 /etc/docker/daemon.json 中调整 bip 或 default-address-pools,然后重启 Docker 服务。
四、抓包定位
当上面的检查都正常却依然不通时,可以在宿主机上抓包,分别观察 docker0、veth 接口和物理网卡上是否有对应流量:
tcpdump -i docker0 -nn port 8080
tcpdump -i eth0 -nn port 8080
如果 docker0 上能看到请求但没有回包,问题多半在容器内的服务或容器内的路由;如果请求根本没到 docker0,则重点检查 iptables 和宿主机路由。
总结
bridge 模式的核心就是:docker0 网桥加 veth 对负责二层连通,iptables 负责 NAT 与端口映射。排查时按服务是否监听正确地址、端口映射与 NAT 规则、IP 转发与防火墙、DNS、网段冲突、抓包这个顺序一层层确认,大部分问题都能快速定位。希望本文对你理解 Docker 网络有所帮助。
- 点赞
- 收藏
- 关注作者
评论(0)