1. 程式人生 > 實用技巧 >容器(五)容器間通訊的三種方式【30】

容器(五)容器間通訊的三種方式【30】

(五)容器間通訊的三種方式

容器之間可通過 IP,Docker DNS Server 或 joined 容器三種方式通訊。

(1)IP 通訊

從上一節的例子可以得出這樣一個結論:兩個容器要能通訊,必須要有屬於同一個網路的網絡卡。

滿足這個條件後,容器就可以通過 IP 互動了。具體做法是在容器建立時通過--network指定相應的網路,或者通過docker network connect將現有容器加入到指定網路。可參考上一節 httpd 和 busybox 的例子,這裡不再贅述。

(2)Docker DNS Server

​ 通過 IP 訪問容器雖然滿足了通訊的需求,但還是不夠靈活。因為我們在部署應用之前可能無法確定 IP,部署之後再指定要訪問的 IP 會比較麻煩。對於這個問題,可以通過 docker 自帶的 DNS 服務解決。

​ 從 Docker 1.10 版本開始,docker daemon 實現了一個內嵌的 DNS server,使容器可以直接通過“容器名”通訊。方法很簡單,只要在啟動時用 --name 為容器命名就可以了。

下面啟動兩個容器 bbox1 和 bbox2:

root@cuiyongchao:~# docker run -it --network my_net2 --name bbox1 busybox
/ # ip a
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
168: eth0@if169: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:16:00:05 brd ff:ff:ff:ff:ff:ff
    inet 172.22.0.5/16 brd 172.22.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # 


啟動bbox2,並測試:

root@cuiyongchao:~# docker run -it --network my_net2 --name bbbox2 busybox
/ # ip a
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
170: eth0@if171: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:16:00:06 brd ff:ff:ff:ff:ff:ff
    inet 172.22.0.6/16 brd 172.22.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping bbox1 -c 3
PING bbox1 (172.22.0.5): 56 data bytes
64 bytes from 172.22.0.5: seq=0 ttl=64 time=0.183 ms
64 bytes from 172.22.0.5: seq=1 ttl=64 time=0.057 ms
64 bytes from 172.22.0.5: seq=2 ttl=64 time=0.096 ms
--- bbox1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.057/0.112/0.183 ms
/ # 

​ 使用 docker DNS 有個限制:只能在 user-defined 網路中使用。也就是說,預設的 bridge 網路是無法使用 DNS 的。下面驗證一下:

啟動bbox3:

root@cuiyongchao:~# docker run -it --name bbox3 busybox
/ # ip a
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
172: eth0@if173: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # 

啟動bbox4,並測試:

root@cuiyongchao:~# docker run -it --name bbox4 busybox
/ # ip a
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
174: eth0@if175: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:06 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.6/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping bbox3 -c 3
ping: bad address 'bbox3'
/ # 

(3)joined 容器

​ joined 容器是另一種實現容器間通訊的方式。joined 容器非常特別,它可以使兩個或多個容器共享一個網路棧,共享網絡卡和配置資訊,joined 容器之間可以通過 127.0.0.1 直接通訊。請看下面的例子:

利用現有的httpd容器:

root@cuiyongchao:~# docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS               NAMES
631d88d3f0d9        httpd               "bash"               About an hour ago   Up About an hour    80/tcp              elated_volhard

然後建立 busybox 容器並通過--network=container:elated_volhard指定 jointed 容器為 elated_volhard:

root@cuiyongchao:~# docker run -it --network container:elated_volhard busybox
/ # ip a
162: eth0@if163: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    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
166: eth1@if167: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:16:00:04 brd ff:ff:ff:ff:ff:ff
    inet 172.22.0.4/16 brd 172.22.255.255 scope global eth1
       valid_lft forever preferred_lft forever

請注意 busybox 容器中的網路配置資訊,下面我們檢視一下 elated_volhard的網路:

root@631d88d3f0d9:/usr/local/apache2# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 4963  bytes 11037968 (10.5 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4848  bytes 263563 (257.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.22.0.4  netmask 255.255.0.0  broadcast 172.22.255.255
        ether 02:42:ac:16:00:04  txqueuelen 0  (Ethernet)
        RX packets 19  bytes 1370 (1.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3  bytes 182 (182.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

​ 看!busybox 和 elated_volhard 的網絡卡 mac 地址與 IP 完全一樣,它們共享了相同的網路棧。busybox 可以直接用 127.0.0.1 訪問 web1 的 http 服務。

joined 容器非常適合以下場景:

  1. 不同容器中的程式希望通過 loopback 高效快速地通訊,比如 web server 與 app server。
  2. 希望監控其他容器的網路流量,比如執行在獨立容器中的網路監控程式。