我想了解桥接的docker0接口是如何工作的。
- 当docker守护进程启动时,它创建一个桥接设备docker0;
- 当容器启动时,它创建一个接口vthn并绑定到docker0
假设我们从容器内部向外部主机发出ping命令
[root@f505f022eb5b app]# ping 130.49.40.130
PING 130.49.40.130 (130.49.40.130) 56(84) bytes of data.
64 bytes from 130.49.40.130: icmp_seq=1 ttl=52 time=11.9 ms
所以很明显我的主机eth0收到了这个ping,但是这个包是如何转发到容器的呢?有几个问题要问
- eth0和docker0没有桥接,docker0如何从eth0获得数据包?
- 即使docker0得到了数据包,它是如何在内部向vth0发送数据包的?它内部是否维护一些映射,以便它可以在不同的mac地址之间转换数据包?
- iptables在这里是如何关联的?
欢呼。
Docker在这里并没有做任何特别神奇的事情,你的问题也不是真正依赖于Docker。
docker0
只是一个网桥。一旦这个桥接被创建(在启动docker服务时),您就可以假设一台新机器(在这种情况下是VM/docker形式)已经加入了您的网络。
当从主机ping docker容器时,或者反之亦然,你基本上是在ping网络中的另一台机器。
关于docker,除非你创建了一个新的网络接口(我怀疑没有,因为你正在ping eth0
),你基本上是在ping你自己。
如果您运行容器为:
docker run -i -t --rm -p 10.0.0.99:80:8080 ubuntu:16.04
你告诉docker在iptables中创建一个NAT规则,将任何到10.0.0.99:80
的数据包转发到端口8080
上的docker容器。
当你运行容器时:
docker run -i -t --rm -p --net=host ubuntu:16.04
那么你是说docker容器应该有与主机相同的网络堆栈,所以所有要到主机的数据包也将通过docker0
桥到达你的docker容器
回答您的问题,容器如何ping外部主机,这也是通过NAT实现的。
使用sudo iptables -t nat -L
您可能会看到类似于下面的内容(docker子网可能不同)
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 anywhere
这基本上是说NAT任何来自docker子网的传出数据包。因此,传出的数据包将看起来来自docker主机。当ping包返回时,NAT表将被用来确定是一个docker主机实际发出了请求,并且数据包被转发到docker服务器。