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沒被占用,可以使用。