在咱们使用的 v18.09 版本中 官方文档,官方文档给出了一下如下五种网络驱动模型,以下:docker
可是有过 docker 使用经验的朋友,可能都知道还有另一种驱动模型,即 container 容器网络驱动模型,这种模型跟 host 类型有些相似,只不过 host 类型是容器和宿主机共享网络名称空间,而 container 类型是多个容器之间共享网络名称空间。json
注意:这里咱们提到共享网络名称空间(host & container 网络驱动模型),可是实际上除了网络名称空间外,还有 IPC、UTS 两个名称空间被共享,也就是说容器仅 MOUNT、PID、USER 这三个名称空间是本身独有的!
对于 container 网络模型,在生产上主要用于两个容器间的高效通讯,官方文档上虽然已经隐藏了该类型,可是我在测试后发现依然能够正常使用。不过你们要注意,若是没有特别需求,仍是不要使用这种模型了。网络
咱们来看下常见的网络驱动模型架构图:
其中图中 Closed container 对应咱们上面提到的 none 网络模型;Bridged container 对应 bridge 模型;Joined container 对应 container 网络模型;Open container 则对应 host 网络模型。
下面咱们对常见的网络驱动模型进行讲解与演示。架构
bridge 是 docker 上默认的容器网络模型,该模型默认会建立一个 docker0 的网桥,网桥地址为 172.16.0.1
,链接到该网桥上的容器会从地址段 172.17.0.0/16
中获取一个随机地址。若是咱们想要修改容器的默认网桥信息,能够经过修改 daemon.json
配置文件,官网中给出了示例,以下:socket
{ "bip": "192.168.1.5/24", "fixed-cidr": "192.168.1.5/25", "fixed-cidr-v6": "2001:db8::/64", "mtu": 1500, "default-gateway": "10.20.1.1", "default-gateway-v6": "2001:db8:abcd::89", "dns": ["10.20.1.2","10.20.1.3"] }
你们若是须要修改的,能够参考该配置文件进行修改。
为了更好的演示该网络模型,咱们先中止全部容器。tcp
# 中止并删除全部容器 [root@docker-server ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
【查看当前宿主机网络信息】微服务
[root@docker-server ~]# ip addr show 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 4: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:88:01:70 brd ff:ff:ff:ff:ff:ff inet 172.24.236.96/22 brd 172.24.239.255 scope global dynamic eth0 valid_lft 74261sec preferred_lft 74261sec inet6 fe80::a00:27ff:fe88:170/64 scope link valid_lft forever preferred_lft forever 5: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:83:32:b3 brd ff:ff:ff:ff:ff:ff inet 10.0.3.15/24 brd 10.0.3.255 scope global dynamic eth1 valid_lft 74263sec preferred_lft 74263sec inet6 fe80::a00:27ff:fe83:32b3/64 scope link valid_lft forever preferred_lft forever 6: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:39:1f:ab:bd 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:39ff:fe1f:abbd/64 scope link valid_lft forever preferred_lft forever
由于我实验环境比较特殊,因此启动了两个网卡eth0、eth1
。
咱们能够看到除了在docker daemon
启动后建立的docker0
网卡外,没有其余虚拟网卡,等咱们建立完容器以后,再来对比看下宿主机上的网卡信息。
【查看此时的网桥信息】工具
注:brctl
工具默认没有,须要咱们手动安装bridge-utils
安装包。
[root@docker-server ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242391fabbd no
【建立两个容器】oop
[root@docker-server ~]# docker run --name demo1 --rm -it busybox:latest [root@docker-server ~]# docker run --name demo2 --rm -it busybox:latest [root@docker-server ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 880ca55196da busybox:latest "sh" 26 seconds ago Up 11 seconds demo1 f46be5a89f6d busybox:latest "sh" 18 seconds ago Up 17 seconds demo2
【再查看网卡和网桥信息】学习
[root@docker-server ~]# ip link show 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 4: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000 link/ether 08:00:27:88:01:70 brd ff:ff:ff:ff:ff:ff 5: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000 link/ether 08:00:27:83:32:b3 brd ff:ff:ff:ff:ff:ff 6: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default link/ether 02:42:39:1f:ab:bd brd ff:ff:ff:ff:ff:ff 106: veth0813d85@if105: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default link/ether ca:5e:7e:19:06:dd brd ff:ff:ff:ff:ff:ff link-netnsid 0 108: veth789d62b@if107: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default link/ether 3e:6b:52:7d:27:a3 brd ff:ff:ff:ff:ff:ff link-netnsid 1
[root@docker-server ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242391fabbd no veth0813d85 veth789d62b
能够看到此时多了两个虚拟网卡,并且该网卡是成对出现的,一半链接在宿主机上的 docker 网桥上,一半在容器中。
那么咱们怎么去判断网卡的另外一半是在哪一个容器中,请仔细看视频教程。
那此时咱们如何看容器的 IP 地址,固然能够经过登陆到容器以后再查看,可是比较麻烦,使用 docker [container] inspect
就能够查看,以下:
[root@docker-server ~]# docker inspect demo1 -f {{.NetworkSettings.Networks.bridge.IPAddress}} 172.17.0.2
[root@docker-server ~]# docker inspect demo2 -f {{.NetworkSettings.Networks.bridge.IPAddress}} 172.17.0.3
【容器网络测试】
[root@docker-server ~]# docker exec -it demo1 ping -c 2 baidu.com PING baidu.com (39.156.69.79): 56 data bytes 64 bytes from 39.156.69.79: seq=0 ttl=61 time=6.608 ms 64 bytes from 39.156.69.79: seq=1 ttl=61 time=39.276 ms --- baidu.com ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 6.608/22.942/39.276 ms
【为何网络能通呢】
[root@docker-server ~]# iptables -t nat -L -n Chain PREROUTING (policy ACCEPT) target prot opt source destination DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT) target prot opt source destination MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0 Chain DOCKER (2 references) target prot opt source destination RETURN all -- 0.0.0.0/0 0.0.0.0/0
其中
Chain POSTROUTING (policy ACCEPT) target prot opt source destination MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
该规则的意义是,让全部从 172.17.0.0/16
网段的源地址,发往 !docker0
网卡的数据(即 非本地容器地址)所有作源地址转换,也就是我们以前虚拟化网络模型中的 NAT 模型。如今来看下下面这幅 bridge 模型图,应该能清晰的描绘出数据流了吧。
咱们演示一下该网络模型的建立,以及该网络模型下的网卡特性。
【建立 host 网络模型容器】
[root@docker-server ~]# docker run --name demo3 -it --rm --network host busybox:latest
【查看网络信息】
/ # ip addr show 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 inet6 ::1/128 scope host valid_lft forever preferred_lft forever 4: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000 link/ether 08:00:27:88:01:70 brd ff:ff:ff:ff:ff:ff inet 172.24.236.96/22 brd 172.24.239.255 scope global dynamic eth0 valid_lft 70857sec preferred_lft 70857sec inet6 fe80::a00:27ff:fe88:170/64 scope link valid_lft forever preferred_lft forever 5: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000 link/ether 08:00:27:83:32:b3 brd ff:ff:ff:ff:ff:ff inet 10.0.3.15/24 brd 10.0.3.255 scope global dynamic eth1 valid_lft 70859sec preferred_lft 70859sec inet6 fe80::a00:27ff:fe83:32b3/64 scope link valid_lft forever preferred_lft forever 6: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue link/ether 02:42:39:1f:ab:bd 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:39ff:fe1f:abbd/64 scope link valid_lft forever preferred_lft forever 106: veth0813d85@if105: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0 link/ether ca:5e:7e:19:06:dd brd ff:ff:ff:ff:ff:ff inet6 fe80::c85e:7eff:fe19:6dd/64 scope link valid_lft forever preferred_lft forever 108: veth789d62b@if107: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0 link/ether 3e:6b:52:7d:27:a3 brd ff:ff:ff:ff:ff:ff inet6 fe80::3c6b:52ff:fe7d:27a3/64 scope link valid_lft forever preferred_lft forever
能够看到在 host 网络模型下, docker container 能看到的网络信息和宿主机是同样的,也就是与宿主机共享NET网络名称空间与 IPC 名称空间,那么咱们继续看下其余的名称空间 PID、MOUNT、USER、UTS 。
【名称空间的共享与独享】
# PID 名称空间独享 / # ps PID USER TIME COMMAND 1 root 0:00 sh 16 root 0:00 ps # MOUNT 名称空间独享 / # ls /root/ / # [root@docker-server ~]# ls /root/ a anaconda-ks.cfg # USER 名称空间独享 / # cat /etc/passwd root:x:0:0:root:/root:/bin/sh daemon:x:1:1:daemon:/usr/sbin:/bin/false bin:x:2:2:bin:/bin:/bin/false sys:x:3:3:sys:/dev:/bin/false sync:x:4:100:sync:/bin:/bin/sync mail:x:8:8:mail:/var/spool/mail:/bin/false www-data:x:33:33:www-data:/var/www:/bin/false operator:x:37:37:Operator:/var:/bin/false nobody:x:65534:65534:nobody:/home:/bin/false / # # UTS 名称空间独享 / # hostname docker-server
通常容器只具备宿主机网络的使用权限,而不具备修改权限。
这种网络模型,容器能够直接使用宿主机网络,由于不须要额外的地址转换,因此效率很高。可是容器与宿主机使用相同网络,就致使了网络资源的占用,好比容器占用了tcp 80
端口,那么宿主机就不能在使用这个端口。
一块儿来看下这种网络模型怎么建立:
[root@docker-server ~]# docker run --name demo4 -it --rm --network none busybox / # ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) / #
为何存在这种模型呢?由于企业中有时候还真须要这种容器,好比咱们以前作数据清洗的一个程序,它其实不须要网络,只须要把数据处理完保存到本地便可(固然这借助到容器的“卷存储”知识,咱们后面再说)。
若是同一个宿主机上的不一样容器想要通讯,最容易想到的方法是什么?两个容器都使用 bridge 模型,即至关于容器链接到同一个虚拟网桥上,只要配置好 IP 地址就能够直接基于 tcp/ip 通讯,这种方式固然能够,只不过还有另一种方式,即让两个容器使用相同的网络名称空间,他们之间基于 IPC 通讯,效率更好。下面咱们跟你们演示一下如何建立这种模型:
【建立一个新的容器】
[root@docker-server ~]# docker run --name demo5 --rm -it busybox:latest / #
【建立 container 网络类型容器】
[root@docker-server ~]# docker run --name demo6 --rm -it --network container:demo5 busybox:latest / #
注意:须要指定使用哪一个容器的网络。
【名称空间的共享与独享】
# IPC 共享,两个容器能够直接经过 Unix socket 通讯 # UTS 共享(两个容器中主机名相同) / # hostname 7104b99d8de4 # NET 共享(两个容器中网络信息相同) / # ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:04 inet addr:172.17.0.4 Bcast:172.17.255.255 Mask:255.255.0.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:108 errors:0 dropped:0 overruns:0 frame:0 TX packets:104 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:9969 (9.7 KiB) TX bytes:9597 (9.3 KiB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) # PID 独享 (demo5)/ # ping -c 100 baidu.com & / # ps -ef PID USER TIME COMMAND 1 root 0:00 sh 15 root 0:00 ping -c 100 baidu.com 16 root 0:00 ps -ef (demo6)/ # ps PID USER TIME COMMAND 1 root 0:00 sh 13 root 0:00 ps # MOUNT 独享 (demo6)/ # touch test / # ls bin dev etc home proc root sys test tmp usr var (demo5)/ # ls bin dev etc home proc root sys tmp usr var # USER 独享(busybox 没法测试,你们可使用其余镜像进行测试)
注意:这种网络模型通常用于两个容器之间网络依赖性特别强,相比较 bridge 模型能够提升网络效率,可是一样带来了容器之间的服务依赖。以我们实例为例,demo6 依赖与 demo5 的网络,一旦 demo5 容器终止,则 demo6 也没法使用网络。微服务初衷是想让服务之间解耦,可是这种网络模型反而使二者的依赖程度增高,因此这也多是 docker 官方文档中再也不体现这种网络模型的缘由。
注:更多技术博客请关注 字节教育官网,若是在学习或者本身实验的过程当中遇到问题,及时与做者沟通。【QQ群 374106486】