在咱們使用的 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】