目录
一、Docker网络理论
1.1理解docker0网桥
当我们安装完好后启动Docker,Docker会为我们自动创建一个 docker0
网桥 可以使用ifconfig
命令查看到 如下图:
可以看到 docker0
和服务器上其他网卡级别相同,那 docker0
是不是可以理解成网卡呢?
答案:当然不能
docker0是网桥,可以通过brctl show
命令查看到
[root@instance-xsv07pjt ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02423dff5dcf no
可以把docker0抽象理解成交换机,就好比在公司内网咱们的服务器连接这交换机,服务器与服务器之间就可以相互通信了,把交换机理解成docker0
把服务器理解成 container
,见下图 瞬间豁然开朗:
1.2 veth pair(虚拟网线)
上面说到,公司内网交换机连接服务器,是不是得需要一条物理网线,交换机与服务器两端连接,这样设备才能相互通信。
docker0,与container类似但不是通过 物理网线
连接 而是通过 虚拟网线(veth pair)
veth pair的全称是:virtual ethernet,就是虚拟的网卡设备接口 如下图所示:
1、创建 centos-1
容器 并且安装 ethool
veth pair都是成对出现的这个结论 可以通过 ethtool
命令验证 如下小实验:
docker run -itd --name centos-1 centos:7
docker exec -it centos-1 /bin/bash
yum -y install ethtool
2、查看容器内
[root@instance-xsv07pjt ~]# docker exec centos-1 ethtool -S eth0
NIC statistics:
peer_ifindex: 21
3、宿主机查看
[root@instance-xsv07pjt ~]# ip addr
.....
21: veth706c644@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether c6:4a:26:fa:77:f1 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::c44a:26ff:fefa:77f1/64 scope link
valid_lft forever preferred_lft forever
上面小实验验证结果就是 容器内 21
和宿主机 21
组成一对 veth pair设备,彼此流量互通!
总结:
- 1、
veth pair
全称是virtual ethernet - 2、
veth pair
是成对出现的一种虚拟网络设备接口
二、容器网络互通理论
2.1小实验:容器之间是否可以通信?
1、首先创建两个Nginx容器
docker run -itd --name nginx-1 nginx:1.18.0
docker run -itd --name nginx-2 nginx:1.18.0
nginx-1:172.17.0.3
nginx-2:172.17.0.4
它们的网关都是172.17.0.1
也就是docker0,如下图所示:
2、验证两个container能否通信
docker exec nginx-1 curl 172.17.0.4
......
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
很显然 实验结果是网络可以相互通信!
2.2为什么?容器之间可以相互通信?
1、当我们使用 172.17.0.3
curl 172.17.0.4
时 172.17.0.3
必须按照 以太网协议
将数据封装好 如:
src ip = 172.17.0.3
src mac = 172.17.0.3的mac地址
dst ip = 172.17.0.4
dst mac = 172.17.0.4的mac地址
2、172.17.0.3
首先会在本地缓存查找 172.17.0.4
的mac地址,如果没有则发送arp请求,可以使用arp -n
名称查看到是否有缓存
arp -n
3、arp请求大致如下:
- 这是一个arp请求包
- 我的ip地址是:172.17.0.3
- 我的mac地址是:172.17.0.3的mac地址
- 请问:ip地址为:172.17.0.4的机器,你的mac地址是多少?
4、172.17.0.3
会查询自己的路由表,将这个arp请求从自己的gateway发送出去
# 172.17.0.3容器里面查看 `route -n`
[root@7494780ab73b /]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
我们会发现 172.17.0.3
的网关地址其实就是docker0
所以这个arp请求包会被发送到docker0上,由docker0拿到这个arp包发现,目标ip是172.17.0.4并不是自己,所以docker0会进一步将这个arp请求报文广播出去,所有在172.17.0.0网段的容器都能收到这个报文!其中就包含了咱们要找的172.17.0.4
。
那172.17.0.4
收到这个arp报文后,会判断,哦!目标ip就是自己的ip,于是它将自己的mac地址填充到arp报文中返回给docker0!
172.17.0.3
拿到``172.17.0.4`的mac地址 以太网协议需要信息齐全了 然后就可以通信了!
2.3总结:
1、172.17.0.3
会查询自己的arp缓存是否有 172.17.0.4
的mac地址,如果有就可以直接通信,没有则需要发送arp请求。
2、172.17.0.3
会查询自己的路由表,将这个arp请求从自己的gateway(docker0)发送出去
3、docker0 广播这个arp请求 172.17.0.0网段的容器都能收到这个报文
4、172.17.0.4
收到这个请求 填写自己的mac地址返给 docker0
5、以太网协议需要信息齐全了 然后就可以通信了!
三、Docker网络模式
Docker 有 bridge、none、host、container 四种网络模式,提供网络隔离、端口映射、容器间互通网络等各种支持
1、bridge模式:
默认网络模式,通过网桥进行网络通信,也就是咱们上面介绍的 就不画图解释了
2、none模式:
这种网络模式下容器只有 lo 回环网络,没有其他网卡,这种类型的网络没有办法联网,外界也无法访问它,封闭的网络能很好地保证容器的安全性。极少使用到这种网络
3、host网络
host 模式会让容器与主机共享网络,此时映射的端口可能会生产冲突,但是容器的其余部分(文件系统、进程等)依然是隔离的,此时容器与宿主机共享网络。