Docker 容器网络通信原理

2026-05-04 16:16 Docker 容器网络通信原理已关闭评论

Docker 容器网络通信原理:我用 3 个实战案例彻底搞懂了它

结论先行:Docker 容器网络的核心是 Linux 网络命名空间 + veth pair + 网桥,搞懂这三样,99% 的容器网络问题你都能自己解决。


1. 写在前面:为什么我要研究这个?

刚接触 Docker 那会儿,我遇到一个经典场景:docker run -p 8080:80 nginx 后,浏览器访问 localhost:8080 就能看到页面。当时觉得“好神奇”,但后来生产环境里容器间通信失败、跨主机网络不通,我才意识到——不懂原理,就是盲人摸象

这篇文章是我从“能用”到“懂原理”的实战记录,每个命令我都亲手敲过,每个坑我都踩过。


2. 三个核心概念,一次讲透

2.1 网络命名空间(Network Namespace)

Docker 为每个容器创建独立的网络命名空间,相当于给容器一个“虚拟网络环境”。

验证一下:

# 查看本机所有网络命名空间
sudo lsns -t net

# 启动一个容器,查看它的网络命名空间
docker run -d --name test nginx
sudo lsns -t net | grep nginx


![宿主机端口到容器端口的流量转发流程](imgs/iptables DNAT端口映射.png)

你会发现容器有自己的网络栈:自己的 lo、eth0,自己的路由表,自己的 iptables 规则。

注意:默认情况下,容器内的进程看不到宿主机的网络设备,反之亦然。

2.2 veth pair(虚拟以太网对)

veth pair 是一对虚拟网卡,像一根虚拟网线——一端在容器里,一端在宿主机上。

实战创建一对 veth:

# 创建一对 veth
sudo ip link add veth0 type veth peer name veth1

# 查看这对网卡
ip link | grep veth

你会看到两个网卡,它们像连在一起的管道:数据从 veth0 进,从 veth1 出。

Docker 就是靠这个把容器“插”到宿主机网络里的。

2.3 网桥(Bridge)

Docker 默认创建一个叫 docker0 的网桥,所有容器通过 veth pair 连到这个网桥上,实现相互通信。

查看 docker0 网桥:

ip addr show docker0
# 输出类似:inet 172.17.0.1/16

查看容器如何连接:

docker network inspect bridge

你会看到每个容器都分配了 172.17.0.x 的 IP,并且通过 veth 对连到 docker0。


3. 实战案例一:容器间通信

场景

启动两个容器,让它们互相 ping 通。

操作步骤

# 启动两个容器
docker run -d --name c1 nginx
docker run -d --name c2 nginx

# 查看它们的 IP
docker inspect c1 | grep IPAddress
docker inspect c2 | grep IPAddress
# 假设 c1=172.17.0.2, c2=172.17.0.3

# 从 c1 ping c2
docker exec c1 ping 172.17.0.3

能通! 原理就是:c1 的 veth 端在 docker0 上,c2 的也在,docker0 像交换机一样转发数据包。

踩坑记录

我一开始以为 docker exec c1 ping c2(用容器名)也能通,结果报错 ping: c2: Name or service not known默认 bridge 网络不支持 DNS 解析容器名,需要自定义网络才行。


4. 实战案例二:宿主机与容器通信

场景

从宿主机访问容器的服务。

操作步骤

# 启动一个暴露端口的容器
docker run -d --name web -p 8080:80 nginx

# 宿主机访问
curl localhost:8080

能通! 原理是 iptables 的 DNAT 规则把宿主机 8080 端口的流量转发到容器 80 端口。

查看规则:

sudo iptables -t nat -L -n | grep 8080
# 输出:DNAT       tcp  --  0.0.0.0/0  0.0.0.0/0   tcp dpt:8080 to:172.17.0.2:80

踩坑记录

有次我改了宿主机防火墙规则,iptables -F 清空了所有规则,结果容器端口映射失效了。Docker 的端口映射依赖 iptables,别乱清!


5. 实战案例三:跨主机容器通信(Overlay 网络)

场景

两台宿主机上的容器需要通信,但物理网络不通。

操作步骤

# 在每台宿主机上初始化 Swarm
docker swarm init

# 创建 overlay 网络
docker network create -d overlay my-overlay

# 在任意节点启动服务
docker service create --name app --network my-overlay nginx

原理:Overlay 网络使用 VXLAN 技术,在宿主机之间建立隧道,把容器数据包封装在 UDP 里传输。

查看隧道:

# 在宿主机上查看 VXLAN 接口
ip link | grep vxlan

踩坑记录

跨主机通信需要 所有宿主机之间 4789 端口(VXLAN 默认端口)互通。我第一次配置时忘了开防火墙端口,折腾了两小时才发现。


6. 网络排查三板斧

当容器网络出问题时,我按这个顺序查:

1. 检查网络命名空间

# 进入容器的网络命名空间
docker run -it --rm --net=container:<容器ID> nicolaka/netshoot
# 然后执行 ip addr, route, iptables-save 等命令

2. 检查网桥和 veth

# 查看网桥上的设备
sudo brctl show docker0

# 查看所有 veth 对
ip link | grep veth

3. 抓包分析

# 在宿主机上抓容器 eth0 的包
tcpdump -i docker0 host 172.17.0.2

注意netshoot 镜像是我最常用的网络调试工具包,内置了 curl、ping、tcpdump、nslookup 等。


7. 核心总结

  1. 容器网络本质:网络命名空间隔离 + veth pair 连接 + 网桥/bridge 转发
  2. 端口映射:依赖 iptables DNAT,别乱清规则
  3. 跨主机通信:需要 Overlay 网络,确保 VXLAN 端口(4789)互通
  4. 排查工具:netshoot 镜像 + brctl + tcpdump 三板斧

最后一句经验:别怕看底层网络命令,ip linkip netnsiptables 这些命令你用得越熟,Docker 网络对你来说就越透明。


8. 延伸思考

  • 如果你需要更精细的网络隔离,可以试试 Macvlan 网络模式,让容器直接使用宿主机物理网卡的 IP
  • 生产环境建议使用 Calico 或 Cilium 这类 CNI 插件,它们支持更高级的网络策略和加密
  • 下次遇到“容器无法访问外网”的问题,先检查宿主机的 ip_forward 是否开启:sysctl net.ipv4.ip_forward

你可能感兴趣的文章

来源:每日教程每日一例,深入学习实用技术教程,关注公众号TeachCourse
转载请注明出处: https://teachcourse.cn/4089.html ,谢谢支持!

资源分享

Android事件分发流程测试运用 Android事件分发流程测试运用
Genymotion如何添加下载过的设备? Genymotion如何添加下载过的设备
抢一张火车票回家过年 抢一张火车票回家过年
python读取markdown文件内容 python读取markdown文件内容

评论已关闭!