docker(7):docker容器的四种网络类型
docker(7):docker容器的四种网络类型
https://www.cnblogs.com/along21/p/10233746.html
https://www.cnblogs.com/zuxing/articles/8780661.html
https://www.cnblogs.com/luoahong/p/10288932.html
1 docker的四种网络模式
1)docker四种网络模式如下:
- Bridge contauner 桥接式网络模式(默认)
- Host(open) container 开放式网络模式,和宿主机共享网络
- Container(join) container 联合挂载式网络模式,和其他容器共享网络
- None(Close) container 封闭式网络模式,不为容器配置网络
(2)可以通过docker network命令查看
[root@docker-136 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE f50feb8398ad bridge bridge local 41e6b3ae3e5d host host local 906b0f4bce31 none null local [root@docker-136 ~]#
(3)docker run --network 命令可以指定使用网络模式
2 bridge网络模式—默认
2.1 介绍
当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上,所以有默认地址172.17.0.0/16的地址。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
[root@docker-136 ~]# ifconfig docker0 docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 inet6 fe80::42:aaff:feaf:2ce prefixlen 64 scopeid 0x20<link> ether 02:42:aa:af:02:ce txqueuelen 0 (Ethernet) RX packets 405 bytes 31320 (30.5 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 416 bytes 474445 (463.3 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。
[root@docker-136 ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242aaaf02ce no veth4b21400 veth5d9876f virbr0 8000.000000000000 no
bridge模式是docker的默认网络模式,不写--net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。
[root@docker-136 ~]# iptables -t nat -vnL Chain PREROUTING (policy ACCEPT 2185 packets, 165K bytes) pkts bytes target prot opt in out source destination 49 3116 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT 73 packets, 18601 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 53 packets, 3708 bytes) pkts bytes target prot opt in out source destination 0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT 2156 packets, 149K bytes) pkts bytes target prot opt in out source destination 10 625 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0 81 5149 SNAT all -- * * 10.1.0.0/24 0.0.0.0/0 to:192.168.0.136 0 0 SNAT all -- * * 10.1.0.0/24 0.0.0.0/0 to:192.168.0.136 0 0 MASQUERADE tcp -- * * 172.17.0.3 172.17.0.3 tcp dpt:80 Chain DOCKER (2 references) pkts bytes target prot opt in out source destination 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0 1 64 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.3:80 [root@docker-136 ~]#
2.2 bridge模式示意图
2.3 bridge模式下容器的通信
https://www.cnblogs.com/zuxing/articles/8780661.html
在bridge模式下,连在同一网桥上的容器可以相互通信(若出于安全考虑,也可以禁止它们之间通信,方法是在DOCKER_OPTsS变量中设置–icc=false,这样只有使用–link才能使两个容器通信)。
Docker可以开启容器间通信(意味着默认配置--icc=true),也就是说,宿主机上的所有容器可以不受任何限制地相互通信,这可能导致拒绝服务攻击。进一步地,Docker可以通过--ip_forward和--iptables两个选项控制容器间、容器和外部世界的通信。
容器也可以与外部通信,我们看一下主机上的Iptable规则,可以看到这么一条
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
这条规则会将源地址为172.17.0.0/16的包(也就是从Docker容器产生的包),并且不是从docker0网卡发出的,进行源地址转换,转换成主机网卡的地址。这么说可能不太好理解,举一个例子说明一下。假设主机有一块网卡为eth0,IP地址为192.168.0.136/24,网关为192.168.0.254。从主机上一个IP为172.17.0.1/16的容器中ping百度(180.76.3.151)。IP包首先从容器发往自己的默认网关docker0,包到达docker0后,也就到达了主机上。然后会查询主机的路由表,发现包应该从主机的eth0发往主机的网关10.10.105.254/24。接着包会转发给eth0,并从eth0发出去(主机的ip_forward转发应该已经打开)。这时候,上面的Iptable规则就会起作用,对包做SNAT转换,将源地址换为eth0的地址。这样,在外界看来,这个包就是从192.168.0.136上发出来的,Docker容器对外是不可见的。
那么,外面的机器是如何访问Docker容器的服务呢?我们首先用下面命令创建一个含有web应用的容器,将容器的80端口映射到主机的80端口。
docker run --name web1 -d -p 80:80 nginx docker run --name web2 -d -p 81:80 nginx
然后查看Iptable规则的变化,发现多了这样一条规则:
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.3:80
[root@docker-136 ~]# iptables -t nat -vnL Chain PREROUTING (policy ACCEPT 4 packets, 238 bytes) pkts bytes target prot opt in out source destination 49 3116 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT 4 packets, 238 bytes) pkts bytes target prot opt in out source destination 10 625 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0 81 5149 SNAT all -- * * 10.1.0.0/24 0.0.0.0/0 to:192.168.0.136 0 0 SNAT all -- * * 10.1.0.0/24 0.0.0.0/0 to:192.168.0.136 0 0 MASQUERADE tcp -- * * 172.17.0.3 172.17.0.3 tcp dpt:80 0 0 MASQUERADE tcp -- * * 172.17.0.4 172.17.0.4 tcp dpt:80 Chain DOCKER (2 references) pkts bytes target prot opt in out source destination 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0 1 64 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.3:80 0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:81 to:172.17.0.4:80 [root@docker-136 ~]#
此条规则就是对主机eth0收到的目的端口为80的tcp流量进行DNAT转换,将流量发往192.168.0.136:80,也就是我们上面创建的Docker容器。所以,外界只需访问192.168.0.136:80就可以访问到容器中的服务。
除此之外,我们还可以自定义Docker使用的IP地址、DNS等信息,甚至使用自己定义的网桥,但是其工作方式还是一样的。
3 None类型
简介:不为容器配置任何网络功能,--net=none
3.1 创建容器
[root@docker-136 ~]# docker images | grep centos centos-ssh-nginx-dockerfile v1 140fbf3f1540 4 days ago 712MB centos-ssh-nginx-dockerfile v2 140fbf3f1540 4 days ago 712MB 192.168.0.136:5000/centos-7-ssh-nginx v1 93af120d6d0b 5 days ago 413MB centos-7-ssh-nginx v1 93af120d6d0b 5 days ago 413MB centos7-ssh v1 1b4f8be39f52 5 days ago 316MB centos latest 9f38484d220f 5 months ago 202MB [root@docker-136 ~]# docker run -d --name none-nework --network none centos7-ssh:v1 b972dfb00b9596a78f75509641c6220f582d22b62c2973c9736b80d95f9d28d2 [root@docker-136 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b972dfb00b95 centos7-ssh:v1 "/usr/sbin/init" 3 minutes ago Up 2 minutes none-nework 22b6f5232114 registry "/entrypoint.sh /etc…" 18 hours ago Up 18 hours 0.0.0.0:5000->5000/tcp kind_mclaren
3.2 查看IP
[root@docker-136 ~]# docker exec -it b972dfb00b95 /bin/bash [root@b972dfb00b95 /]# ifconfig lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1000 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 [root@b972dfb00b95 /]# ping www.baidu.com ping: www.baidu.com: Name or service not known [root@docker-136 ~]#
3.3 查看容器网络信息
[root@docker-136 ~]# docker inspect b972dfb00b95 …. "Networks": { "none": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "906b0f4bce31ffcda248ab14fe5584d7f23a6e0074da1a5e126367fd77d4f330", "EndpointID": "d45572dca14013869fe7e8ef1a8de4131939de67b26c0bf5b732468e212b4706", "Gateway": "", "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "", "DriverOpts": null } } } ….
4 Container类型
简介:与另一个运行中的容器共享Network Namespace,--net=container:containerID
4.1 新建一个标准容器
[root@docker-136 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1ddcce8e072c centos7-ssh:v1 "/usr/sbin/init" 8 seconds ago Up 4 seconds 22/tcp centos-base 22b6f5232114 registry "/entrypoint.sh /etc…" 18 hours ago Up 18 hours 0.0.0.0:5000->5000/tcp kind_mclaren [root@docker-136 ~]# docker exec -it 1ddcce8e072c /bin/bash [root@1ddcce8e072c /]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.3 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet) RX packets 8 bytes 656 (656.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1000 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 [root@1ddcce8e072c /]# exit [root@docker-136 ~]# docker inspect 1ddcce8e072c …… "MacAddress": "02:42:ac:11:00:03", "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "f50feb8398ad12138dd351c68442686fcd9ba533cd6a2f9472cc85414c2a5cca", "EndpointID": "084ee8b3aa39abd30d76104be9112496fb355de3b6fdc5e7d6beec3efb10aac0", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.3", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:03", "DriverOpts": null } } } } ] [root@docker-136 ~]#
4.2 新建一个container网络的容器
[root@docker-136 ~]# docker run -d --name web-1 --network container:centos-base centos7-ssh:v1 0ce6a9557d9291683557738ce21b1a4aa093251b9fbef432d214a6b5dabc1df4 [root@docker-136 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0ce6a9557d92 centos7-ssh:v1 "/usr/sbin/init" 4 seconds ago Up 3 seconds web-1 1ddcce8e072c centos7-ssh:v1 "/usr/sbin/init" 11 minutes ago Up 11 minutes 22/tcp centos-base 22b6f5232114 registry "/entrypoint.sh /etc…" 18 hours ago Up 18 hours 0.0.0.0:5000->5000/tcp kind_mclaren [root@docker-136 ~]# docker exec -it web-1 /bin/bash [root@1ddcce8e072c /]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.3 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet) RX packets 8 bytes 656 (656.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1000 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 [root@1ddcce8e072c /]# [root@docker-136 ~]# docker inspect web-1 [ "NetworkSettings": { "Bridge": "", "SandboxID": "", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": {}, "SandboxKey": "", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "", "Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "MacAddress": "", "Networks": {} } } ]
4.3 总结
container网络类型:和其他容器共享网络IP
容器直接端口尽量不要冲突,如果冲突,先到先得。
5 Host类型
简介:与主机共享Network Namespace,--net=host
5.1 创建host网络类型容器
[root@docker-136 ~]# docker run -d --name host-1 --network host centos-7-ssh-nginx:v1 083ce00a90c84f2ab741eee2a21529b73ce8421e42e6eff2bbf348d0aab35b28 [root@docker-136 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 083ce00a90c8 centos-7-ssh-nginx:v1 "/usr/sbin/init" 12 seconds ago Up 12 seconds host-1 0ce6a9557d92 centos7-ssh:v1 "/usr/sbin/init" 9 minutes ago Up 9 minutes web-1 1ddcce8e072c centos7-ssh:v1 "/usr/sbin/init" 21 minutes ago Up 21 minutes 22/tcp centos-base 22b6f5232114 registry "/entrypoint.sh /etc…" 18 hours ago Up 18 hours 0.0.0.0:5000->5000/tcp kind_mclaren
5.2 容器IP、主机名与宿主机一致
[root@docker-136 /]# ifconfig docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 inet6 fe80::42:6dff:fec0:d903 prefixlen 64 scopeid 0x20<link> ether 02:42:6d:c0:d9:03 txqueuelen 0 (Ethernet) RX packets 41974 bytes 161399603 (153.9 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 27564 bytes 157458449 (150.1 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.0.136 netmask 255.255.255.0 broadcast 192.168.0.255 inet6 fe80::20c:29ff:fe51:f5dd prefixlen 64 scopeid 0x20<link> ether 00:0c:29:51:f5:dd txqueuelen 1000 (Ethernet) RX packets 263385 bytes 290302159 (276.8 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 163121 bytes 205037243 (195.5 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 2332 bytes 118920 (116.1 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 2332 bytes 118920 (116.1 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 veth6f1393a: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet6 fe80::fc11:94ff:fe5d:3758 prefixlen 64 scopeid 0x20<link> ether fe:11:94:5d:37:58 txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 8 bytes 656 (656.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 veth906a82d: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet6 fe80::34ea:72ff:feb9:8ef9 prefixlen 64 scopeid 0x20<link> ether 36:ea:72:b9:8e:f9 txqueuelen 0 (Ethernet) RX packets 25808 bytes 154820834 (147.6 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 3564 bytes 242812 (237.1 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 [root@docker-136 ~]# hostname docker-136 [root@docker-136 ~]#
5.3 容器启动服务测试
[root@docker-136 ~]# netstat -lntp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN - tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN - tcp6 0 0 :::5000 :::* LISTEN - tcp6 0 0 :::22 :::* LISTEN - tcp6 0 0 ::1:25 :::* LISTEN - tcp6 0 0 :::10050 :::* LISTEN - [root@docker-136 ~]# [root@docker-136 ~]# /usr/sbin/sshd -D [root@docker-136 ~]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 03:09 ? 00:00:00 /usr/sbin/init root 6 0 0 03:10 pts/0 00:00:00 /bin/bash root 26 6 0 03:11 pts/0 00:00:00 ps -ef [root@docker-136 ~]# nginx -g 'daemon on;' [root@docker-136 ~]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 03:09 ? 00:00:00 /usr/sbin/init root 6 0 0 03:10 pts/0 00:00:00 /bin/bash root 32 0 4 03:11 ? 00:00:00 nginx: master process nginx -g daemon on; nginx 33 32 0 03:11 ? 00:00:00 nginx: worker process root 34 6 6 03:11 pts/0 00:00:00 ps -ef [root@docker-136 ~]# netstat -lntp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 32/nginx: master pr tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN - tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN - tcp6 0 0 :::5000 :::* LISTEN - tcp6 0 0 :::80 :::* LISTEN 32/nginx: master pr tcp6 0 0 :::22 :::* LISTEN - tcp6 0 0 ::1:25 :::* LISTEN - tcp6 0 0 :::10050 :::* LISTEN - [root@docker-136 ~]#
5.4 容器网络类型查看
[root@docker-136 ~]# docker inspect 083ce00a90c8 ….. "Networks": { "host": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "41e6b3ae3e5d856e9663b56c75a68c58f8225a5da9c33c7b61e8fa007915b669", "EndpointID": "f2a45503a0c3c6e03cde148779172db6fdd4a0787c4d56aafb6d5206c2b4c898", "Gateway": "", "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "", "DriverOpts": null } }
5.5 总结
- IP、主机名和宿主机是一样
- netstat -lntup的结果也是一样
- 但是容器看不到主机的程序
- 和宿主机端口冲突,宿主机占用了22端口,容器无法使用,80没被占用,可以使用。