1. docker網絡介紹
大量的互聯網應用服務需要多個服務組件,這往往需要多個容器之間通過網絡通信進行相互配合。
docker 網絡從覆蓋范圍可分為單個 host 上的容器網絡和跨多個 host 的網絡。
docker 目前提供了映射容器端口到宿主主機和容器互聯機制(映射)來為容器提供網絡服務,在啟動容器的時候,如果不指定參數,在容器外部是沒有辦法通過網絡來訪問容器內部的網絡應用和服務的。
docker 安裝時會自動在host上創建三個網絡,查看一下docker網絡:
[root@alph ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 59cb3737df3c bridge bridge local 8b9081147227 host host local ea6732b465e8 none null local [root@alph ~]#
2. docker none網絡
none 網絡就是什么都沒有的網絡。掛在這個網絡下的容器除了 lo(本地回環地址),沒有其他任何網卡。容器創建時,可以通過 --network=none 指定使用 none 網絡
啟動容器: [root@alph ~]# docker run -itd --network=none --name box reg.yunwei.edu/learn/httpd:latest 18f6521f1ae21775203a3d0efe40b62082a4edb637e074292ab6f6e665cee361 查看: 18f6521f1ae21775203a3d0efe40b62082a4edb637e074292ab6f6e665cee361 [root@alph ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 18f6521f1ae2 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" 7 seconds ago Up 7 seconds box 進入容器: [root@alph ~]# docker exec -it 18f6521f1ae2 /bin/bash 查看ip root@18f6521f1ae2:/usr/local/apache2# ip a #僅有lo 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 root@18f6521f1ae2:/usr/local/apache2# ^C root@18f6521f1ae2:/usr/local/apache2#
none 網絡的應用
封閉的網絡意味着隔離,一些對安全性要求高並且不需要聯網的應用可以使用 none 網絡。
比如某個容器的唯一用途是生成隨機密碼,就可以放到 none 網絡中避免密碼被竊取。
3. host網絡
連接到 host 網絡的容器,共享 docker host 的網絡棧,容器的網絡配置與 host 完全一樣。可以通過 --network=host 指定使用 host 網絡。
[root@alph ~]# docker run -itd --network=host --name box2 reg.yunwei.edu/learn/httpd:latest [root@alph ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d478bbdb1ef8 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" 23 seconds ago Up 22 seconds box2 18f6521f1ae2 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" About an hour ago Up About an hour box [root@alph ~]# docker exec -it d478bbdb1ef8 /bin/sh # ip a 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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:50:56:37:0c:29 brd ff:ff:ff:ff:ff:ff inet 192.168.16.88/24 brd 192.168.16.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:25:8a:98:c6 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:25ff:fe8a:98c6/64 scope link valid_lft forever preferred_lft forever # hostname alph
在容器中可以看到 host 的所有網卡,並且連 hostname 也是 host 的。
直接使用 Docker host 的網絡最大的好處就是性能,如果容器對網絡傳輸效率有較高要求,就可以選擇 host 網絡。
當然不便之處就是犧牲一些靈活性,比如要考慮端口沖突問題,Docker host 上已經使用的端口就不能再用了。
Docker host 的另一個用途是讓容器可以直接配置 host 網路。比如某些跨 host 的網絡解決方案,其本身也是以容器方式運行的,這些方案需要對網絡進行配置,比如管理 iptables。
4. docker bridge 網絡
docker 安裝時會創建一個 命名為 docker0 的 linux bridge。如果不指定--network,創建的容器默認都會掛到 docker0 上。
[root@alph ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242258a98c6 no
當前docker0 上沒有其他網絡設備,創建一個容器查看變化。
[root@alph ~]# docker run -itd --name box3 reg.yunwei.edu/learn/httpd:latest 5ddc5295e266aaf49c897710ccbb1e02273f49b15afd1bdfb8f4dfffc1de9dfe [root@alph ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5ddc5295e266 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" 17 seconds ago Up 17 seconds 80/tcp box3 d478bbdb1ef8 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" 9 minutes ago Up 9 minutes box2 18f6521f1ae2 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" About an hour ago Up About an hour box [root@alph ~]# docker exec -it 5ddc5295e266 /bin/bash root@5ddc5295e266:/usr/local/apache2# ip a 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 6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 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@alph ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242258a98c6 no vethaecb9c8
一個新的網絡接口 vethaecb9c8 被掛到了 docker0 上,vethaecb9c8就是新創建容器的虛擬網卡。eth0@if7和vethaecb9c8是一對 veth pair。veth pair 是一種成對出現的特殊網絡設備,可以把它們想象成由一根虛擬網線連接起來的一對網卡,網卡的一頭(eth0@if7)在容器中,另一頭(vethaecb9c8)掛在網橋 docker0 上,其效果就是將 eth0@if7 也掛在了 docker0 上。
eth0@if7已經配置了ip 172.17.0.2/16,這個網段有配置信息network inspect bridge 決定。
[root@alph ~]# docker network inspect bridge [ { "Name": "bridge", "Id": "59cb3737df3cea7308084fb5c112836f55520e8546cd7e7603949ab4db36a0e4", "Created": "2019-07-15T22:10:23.832317973+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": { "5ddc5295e266aaf49c897710ccbb1e02273f49b15afd1bdfb8f4dfffc1de9dfe": { "Name": "box3", "EndpointID": "cb51e0323762eed6e4ea588cf64f9b0f06ffc79642c71e98008e54b3a3923341", "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": {} } ]
5. 自定義創建網絡
可通過 bridge 驅動創建類似前面默認的 bridge 網絡
(1)利用bridge驅動創建名為my-net2網橋(docker會自動分配網段):
[root@alph ~]# docker network create --driver bridge my-net2
966e69c70ce3eb189be4d993f97e6c572b470f7c74f8104059e27bd04cf9c95a
(2)查看一下當前 host 的網絡結構變化:
[root@alph ~]# docker network list NETWORK ID NAME DRIVER SCOPE 59cb3737df3c bridge bridge local 8b9081147227 host host local 966e69c70ce3 my-net2 bridge local ea6732b465e8 none null local
(3)查看容器bridge網橋配置(bridge就是容器和網橋形成一對veth pair)
[root@alph ~]# docker network inspect bridge my-net2 { "Name": "my-net2", "Id": "966e69c70ce3eb189be4d993f97e6c572b470f7c74f8104059e27bd04cf9c95a", "Created": "2019-07-16T02:25:29.664999007+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", #16為掩碼。提供更多的服務 "Gateway": "172.18.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": {}, "Labels": {} } ]
刪除網絡用命令 rm
[root@alph ~]# docker network create --driver bridge my-net3 596fc585538f6862425300dcdc35b62a759f8b11feb249d142492c5519a6a0c2 [root@alph ~]# docker network list NETWORK ID NAME DRIVER SCOPE 59cb3737df3c bridge bridge local 8b9081147227 host host local 966e69c70ce3 my-net2 bridge local 596fc585538f my-net3 bridge local ea6732b465e8 none null local [root@alph ~]# docker rm my-net3 Error: No such container: my-net3 [root@alph ~]# docker network rm my-net3 my-net3 [root@alph ~]# docker network list NETWORK ID NAME DRIVER SCOPE 59cb3737df3c bridge bridge local 8b9081147227 host host local 966e69c70ce3 my-net2 bridge local ea6732b465e8 none null local
(4)利用bridge驅動創建名為my-net3網橋(用戶自定義網段及網關)
[root@alph ~]# docker run -itd --network=my-net3 --name box4 reg.yunwei.edu/learn/httpd:latest 1fd7e0d3e08345da6e7259fbf6dcb0bf95861ec457236e81125737840032c539 [root@alph ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1fd7e0d3e083 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" 18 seconds ago Up 17 seconds 80/tcp box4 5ddc5295e266 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" About an hour ago Up About an hour 80/tcp box3 d478bbdb1ef8 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" About an hour ago Up About an hour box2 18f6521f1ae2 reg.yunwei.edu/learn/httpd:latest "httpd-foreground" 2 hours ago Up 2 hours box
(5)啟動容器使用新建的my-net3網絡
[root@alph ~]# docker exec -it box4 "docker exec" requires at least 2 arguments. See 'docker exec --help'. Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...] [flags] Run a command in a running container [root@alph ~]# docker exec -it box4 /bin/sh # ip a 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 19: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:16:01:02 brd ff:ff:ff:ff:ff:ff inet 172.22.1.2/24 brd 172.22.1.255 scope global eth0 #自定義的網段 valid_lft forever preferred_lft forever
(6)啟動容器使用my-net3網絡並指定ip(只有使用 --subnet 創建的網絡才能指定靜態 IP,如果是docker自動分配的網段不可以指定ip)
[root@alph ~]# docker run -it --network=my-net3 --ip 172.22.1.10 reg.yunwei.edu/learn/httpd:latest /bin/sh # ip a 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 21: eth0@if22: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:16:01:0a brd ff:ff:ff:ff:ff:ff inet 172.22.1.10/24 brd 172.22.1.255 scope global eth0 valid_lft forever preferred_lft forever
(7)讓已啟動不同vlan的box容器,可以連接到my-net2(其實在box中新建了my-net2的網卡)
[root@alph ~]# docker network connect my-net2 box4 [root@alph ~]# docker exec -it box4 /bin/sh # ip a 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 19: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:16:01:02 brd ff:ff:ff:ff:ff:ff inet 172.22.1.2/24 brd 172.22.1.255 scope global eth0 valid_lft forever preferred_lft forever 23: eth1@if24: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default #連接到box2的網卡 link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff inet 172.18.0.2/16 brd 172.18.255.255 scope global eth1 valid_lft forever preferred_lft forever #
(8)使用--name指定啟動容器名字,可以使用docker自帶DNS通信,但只能工作在user-defined 網絡,默認的 bridge 網絡是無法使用 DNS 的。
docker run -it --network=my_net2 --name=bbox1 busybox
docker run -it --network=my_net2 --name=bbox2 busybox
(9)容器之間的網絡互聯
a). 首先創建一個 db 容器
[root@alph ~]# docker run -dti --name db reg.yunwei.edu/learn/centos:7 2b9cdc455352f8a5e2da50db61fef706089f4abe7ba7c4b91033cc2a55a55bf8
b). 創建一個 web 容器,並使其連接到 db
[root@alph ~]# docker run -dti --name web --link db:dblink reg.yunwei.edu/learn/centos:7 /bin/bash 40bba17b3dfe2ad01d6b80d78230c975e127340170d15a49e8f7c905bbd075fe
-link db:dblink 實際是連接對端的名字和這個鏈接的名字,也就是和 db 容器建立一個叫做 dblink 的鏈接
c). 查看鏈接的情況
[root@alph ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 40bba17b3dfe reg.yunwei.edu/learn/centos:7 "/bin/bash" About a minute ago Up About a minute web 2b9cdc455352 reg.yunwei.edu/learn/centos:7 "/bin/bash" About a minute ago Up About a minute db
d). 使用 ping 命令來測試網絡鏈接的情況
[root@alph ~]# docker exec -it 40bba17b3dfe /bin/bash [root@40bba17b3dfe /]# ping db PING dblink (172.17.0.3) 56(84) bytes of data. 64 bytes from dblink (172.17.0.3): icmp_seq=1 ttl=64 time=48.5 ms 64 bytes from dblink (172.17.0.3): icmp_seq=2 ttl=64 time=0.058 ms
再換到db容器來ping web容器,因為連接是單向的,因此是ping不同的
[root@alph ~]# docker exec -it db /bin/sh sh-4.2# ping web
(10)容器端口映射
在啟動容器的時候,如果不指定參數,在容器外部是沒有辦法通過網絡來訪問容器內部的網絡應用和服務的。
當容器需要通信時,我們可以使用 -P (大)和 -p (小)來指定端口映射。
-P(大) : Docker 會隨機映射一個 49000 ~ 49900 的端口到容器內部開放的網絡端口
-p (小):則可以指定要映射的端口,並且在一個指定的端口上只可以綁定一個容器。
支持的格式有
IP : HostPort : ContainerPort (將Host端口映射給Container)
IP : : ContainerPort (隨機生成一個端口號映射為Container)
IP : HostPort : (類似的,讓容器隨機生成一個端口)
a)映射所有接口地址,此時綁定本地所有接口上的 5000 到容器的 5000 接口,訪問任何一個本地接口的 5000 ,都會直接訪問到容器內部
[root@alph ~]# docker run -itd -p 8081 --name http reg.yunwei.edu/learn/httpd c69494d7692d9cd5aa0ce24c286ad607adb9879f35cb8ce214a1002d8c24c336
通過訪問宿主機的端口號來訪問容器
嘗試在容器http更改html文件,再刷新查看
[root@alph ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2d7cc376dd27 reg.yunwei.edu/learn/httpd "httpd-foreground" About a minute ago Up About a minute 0.0.0.0:8081->80/tcp http [root@alph ~]# docker exec -it http /bin/bash root@2d7cc376dd27:/usr/local/apache2# ls #工作目錄 bin build cgi-bin conf error htdocs icons include logs modules root@2d7cc376dd27:/usr/local/apache2# cd htdocs/ #容器文件目錄 root@2d7cc376dd27:/usr/local/apache2/htdocs# ls index.html root@2d7cc376dd27:/usr/local/apache2/htdocs# echo " It is so beautiful!" >> inde.html

b)多次使用可以實現多個接口的映射
docker run -dti -p 5000:5000 -p 5022:22 centos:7.0 /bin/bash
c)映射到指定地址的指定接口
此時會綁定本地 192.168.4.169 接口上的 5000 到容器的 5000 接口
docker run -dti -p 192.168.4.169:5000:5000 centos:7.0 /bin/bash
d) 映射到指定地址的任意接口
此時會綁定本地 192.168.4.169 接口上的任意一個接口到容器的 5000 接口
docker run -dti -p 192.168.4.169::5000 centos:7.0 /bin/bash
e) 使用接口標記來指定接口的類型
docker run -dti -p 192.168.4.169::5000/UDP centos:7.0 /bin/bash
11) 通過端口映射實現訪問本地的 IP:PORT 可以訪問到容器內的 web
[root@alph ~]# for id in `docker ps -a | awk '{print $1}' | grep -v CONTAINER`;do docker rm -f $id;done [root@alph ~]# docker run -itd --name http reg.yunwei.edu/learn/httpd:latest 34099c67cf07685fa830c1feb143d2f948a5231a48d5d542a285d3cd62a074d4 [root@alph ~]# docker exec -it http /bin/bash root@34099c67cf07:/usr/local/apache2# ls bin build cgi-bin conf error htdocs icons include logs modules root@34099c67cf07:/usr/local/apache2# 將容器http的/usr/local/apache2導出以免丟失目錄下內容 [root@alph ~]# docker cp http:/usr/local/apache2 ./ [root@alph ~]# ls anaconda-ks.cfg apache2 doc_file docker test [root@alph ~]# cd apache2/ [root@alph apache2]# ls bin build cgi-bin conf error htdocs icons include logs modules 將現在在root下的目錄apache2映射給容器下的/usr/local/apache2 [root@alph ~]# docker run -itd -v /root/apache2/:/usr/local/apache2 -p 8081:80 --name http2 reg.yunwei.edu/learn/httpd 31ca9cce1b2c61043bfa385a1572bf9d1bf76fa19a45c8f7b2a63c983f9073a8 映射完成后相當於共享文件夾,在容器創建的文件在宿主機相應目錄下能夠查到,同樣在宿主機相關文件進行的修改對容器有效 [root@alph ~]# docker exec -it http2 /bin/bash root@31ca9cce1b2c:/usr/local/apache2# ls bin build cgi-bin conf error htdocs icons include logs modules root@31ca9cce1b2c:/usr/local/apache2# touch aaaaa root@31ca9cce1b2c:/usr/local/apache2# exit exit [root@alph apache2]# ls aaaaa bin build cgi-bin conf error htdocs icons include logs modules [root@alph apache2]# cd htdocs/ [root@alph htdocs]# ls index.html [root@alph htdocs]# vim index.html <html><body><h1>It works!</h1></body></html> <html><body><h1>It so beautiful!</h1></body></html> 將該容器刪除后其文件將不受影響,再次激活該容器該文件可以繼續使用,這是一種動態的更改。![]()