上一节讲了linux的网络命名空间,创建了veth,然后使两个网络命名空间的网络互通,那么docker创建容器之后,会发现在容器里面是可以访问外网的,而且容器之间的网络是互通的。
1、容器里能访问外网
新建一个容器,进到容器里面ping www.baidu.com,能ping 通
[root@vol ~]# docker run -d --name test1 busybox /bin/sh -c "while true; do sleep 3600;done"
dfe2c0f67d68db7d2b8498ab4ff9a787cde8da9c87f705b0bd685d33b0fab9e5
[root@vol ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dfe2c0f67d68 busybox "/bin/sh -c 'while t…" 35 seconds ago Up 33 seconds test1
[root@vol ~]# docker exec -it dfe2c0f67d68 /bin/sh
/ # ping www.baidu.com
PING www.baidu.com (14.215.177.38): 56 data bytes
64 bytes from 14.215.177.38: seq=0 ttl=53 time=5.337 ms
64 bytes from 14.215.177.38: seq=1 ttl=53 time=9.697 ms
64 bytes from 14.215.177.38: seq=2 ttl=53 time=5.318 ms
^C
--- www.baidu.com ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 5.318/6.784/9.697 ms
/ #
2、再新建一个容器,容器与容器之间网络能互通
## 查看容器ip发现,test1容器 ip为172.17.0.2 test2容器的ip为172.17.0.3
[root@vol ~]# docker exec test1 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
[root@vol ~]# docker exec test2 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
##进入test1容器里,ping test2的ip,发现能ping通
[root@vol ~]# docker exec -it test1 /bin/sh
/ # ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.187 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.118 ms
64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.133 ms
^C
--- 172.17.0.3 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.118/0.146/0.187 ms
/ # exit
进入test2容器ping test1 ip也是一样能通,说明两个容器之间网络是互通的。
原理
其实原理也是类似于上一节所说。实际上就是新建了一对veth,将网络打通了。
1、容器里能访问外网,是因为有一对veth,一端连着容器,一端连着主机的docker0,这样容器就能共用主机的网络了,当容器访问外网时,就会通过NAT进行地址转换,实际是通过iptables来实现的,这里不展开。
2、再新建一个容器,又会生成一对veth,一端连着容器,一端连着docker0网络,这样两个容器都连着docker0,他们就可以互相通信了。这里可以把容器想象为家里的电脑,docker0则是路由器,想要两台电脑在同一局域网,就可以拿两条网线,把他们连到同一个路由器上,这样两台电脑就可以相互通信了。
如图所示:
验证
1、安装brctl工具
2、跟踪网络链路
安装brctl
[root@vol ~]# yum install bridge-utils
Loaded plugins: fastestmirror
Determining fastest mirrors
docker-ce-stable | 3.5 kB 00:00
epel | 5.3 kB 00:00
extras | 2.9 kB 00:00
kubernetes/signature | 454 B 00:00
kubernetes/signature | 1.4 kB 00:00 !!!
。。。省略。。。
查看本机bridge网络以及查看docker网络
已知有两个运行的容器,查看本机的ip地址,发现除了lo,ens160和docker0外,多出了两个veth,运行brctl show会发现bridge网络上连了两个veth,而这两个veth正好是主机上多出的那两个veth,由此可知,主机上veth连在docker0上,那么veth的另一端连着哪里呢?
[root@vol ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
da0dd80d5418 busybox "/bin/sh -c 'while t…" 17 minutes ago Up 17 minutes test2
dfe2c0f67d68 busybox "/bin/sh -c 'while t…" 4 hours ago Up 4 hours test1
[root@vol ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:87:bd:a7 brd ff:ff:ff:ff:ff:ff
inet 172.31.17.54/16 brd 172.31.255.255 scope global noprefixroute ens160
valid_lft forever preferred_lft forever
inet6 fe80::33db:6382:9c3a:12e8/64 scope link tentative dadfailed
valid_lft forever preferred_lft forever
inet6 fe80::a780:a19:68f2:9347/64 scope link tentative dadfailed
valid_lft forever preferred_lft forever
inet6 fe80::a62f:dd94:b9a2:3027/64 scope link tentative dadfailed
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:9d:e3:47:69 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:9dff:fee3:4769/64 scope link
valid_lft forever preferred_lft forever
5: veth9d0b56c@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 52:9f:51:35:0c:b8 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::509f:51ff:fe35:cb8/64 scope link
valid_lft forever preferred_lft forever
7: vethe9de44d@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether f2:b4:4a:9c:41:0a brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::f0b4:4aff:fe9c:410a/64 scope link
valid_lft forever preferred_lft forever
[root@vol ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02429de34769 no veth9d0b56c
vethe9de44d
可以看到veth9d0b56c 刚好是本机的5: veth9d0b56c@if4,而vethe9de44d是对应本机的 7: vethe9de44d@if6,另一端连在哪?
inspect bridge查看bridge的相关信息。发现其中的Containers上有test1和test2容器,说明这两个容器都是连在bridge网络上的。再新建一个容器,会发现又多一个容器连在bridge上。
[root@vol ~]# docker network list
NETWORK ID NAME DRIVER SCOPE
0ee165ccab6f bridge bridge local
baa1cdd2d1e4 host host local
2cb2a0e5dad5 none null local
[root@vol ~]# docker inspect bridge
[
{
"Name": "bridge",
"Id": "0ee165ccab6fa3c171708329bd3ab692376fc46ea4eb04fce93f2e0b3269d640",
"Created": "2020-01-19T16:23:36.392297087+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"da0dd80d5418f7138d1d41fea43e06006d9d3dfe175e68502ba8ba6a809d1f83": {
"Name": "test2",
"EndpointID": "187509eca88c77ba6b1a7bb63f485d6a9e610038142983817d353031b63afba6",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"dfe2c0f67d68db7d2b8498ab4ff9a787cde8da9c87f705b0bd685d33b0fab9e5": {
"Name": "test1",
"EndpointID": "bc27d2081aa69cebf0ee609aa42f00aa4a3cd73e72ff8b6c13eefb4b0b2fab67",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
从上面containers的ip来看,bridge网络连着的是另一半的veth,如下,可以看到容器里的veth ip与bridge上的ip是一致的。
[root@vol ~]# docker exec test1 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
[root@vol ~]# docker exec test2 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
由此可以知道,新建一个docker容器,就会新建一对veth,一端连着本机的docker0,一端连着docker容器,由此实现的docker容器网络互通,以及容器与主机网络互通。
来源:CSDN
作者:wangmiaoyan
链接:https://blog.csdn.net/wangmiaoyan/article/details/104656127