1. 程式人生 > >4. Docker 網路模式-bridge

4. Docker 網路模式-bridge

文章目錄

概述

Docker 強大的原因之一在於多個 Docker 容器之間的互相連線。涉及到連線,就引出了網路通訊的幾種模式。Docker 預設提供了 5 種網路驅動模式。

  • bridge: 預設的網路驅動模式。如果不指定驅動程式,bridge 便會作為預設的網路驅動模式。當應用程式執行在需要通訊的獨立容器(standalone containers)中時,通常會選擇 bridge 模式。
  • host:移除容器和 Docker 宿主機之間的網路隔離,並直接使用主機的網路。host 模式僅適用於 Docker 17.06+。
  • overlay:overlay 網路將多個 Docker 守護程序連線在一起,並使叢集服務能夠相互通訊。您還可以使用 overlay 網路來實現 swarm 叢集和獨立容器之間的通訊,或者不同 Docker 守護程序上的兩個獨立容器之間的通訊。該策略實現了在這些容器之間進行作業系統級別路由的需求。
  • macvlan:Macvlan 網路允許為容器分配 MAC 地址,使其顯示為網路上的物理裝置。 Docker 守護程序通過其 MAC 地址將流量路由到容器。對於希望直連到物理網路的傳統應用程式而言,使用 macvlan 模式一般是最佳選擇,而不應該通過 Docker 宿主機的網路進行路由。
  • none:對於此容器,禁用所有聯網。通常與自定義網路驅動程式一起使用。none 模式不適用於叢集服務。

通過在 Docker 上安裝和使用第三方網路外掛可以算作額外的擴充套件方式。

預設網路

kiritodeMacBook-Pro:~ kirito$ docker network ls
NETWORK ID          NAME                         DRIVER              SCOPE
15315759c263        bridge                       bridge              local
d72064d9febf        host                         host                local
83ea989d3fec        none                         null                local

這 3 個網路包含在 Docker 實現中。執行一個容器時,可以使用 –network 引數指定在哪種網路模式下執行該容器。

這篇文章重點介紹 bridge 模式。 所有 Docker 安裝後都存在的 docker0 網路,這在 Docker 基礎中有過介紹。除非使用 **docker run –network=**選項另行指定,否則 Docker 守護程序預設情況下會將容器連線到 docker0 這個網路。

建立自定義的網路

使用如下命令就可以建立一個名稱為 my-net ,網路驅動模式為 bridge 的自定義網路。

$ docker network create my-net

再次檢視存在的網路可以發現上述命令執行之後產生的變化:

kiritodeMacBook-Pro:~ kirito$ docker network ls
NETWORK ID          NAME                         DRIVER              SCOPE
15315759c263        bridge                       bridge              local
d72064d9febf        host                         host                local
73e32007f19f        my-net                       bridge              local
83ea989d3fec        none                         null                local

使用 busybox 測試容器連通性

BusyBox 是一個集成了一百多個最常用 Linux 命令和工具(如 cat、echo、grep、mount、telnet 、ping、ifconfig 等)的精簡工具箱,它只需要幾 MB 的大小,很方便進行各種快速驗證,被譽為“Linux 系統的瑞士軍刀”。

我們使用 busybox 來測試容器間的網路情況。(一開始我嘗試使用 ubuntu 作為基礎映象來構建測試容器,但 ubuntu 映象刪減了幾乎所有的常用工具,連同 ping,ifconfig 等命令都需要額外安裝軟體,而 busybox 則不存在這些問題。)

使用預設網橋 docker0

kiritodeMacBook-Pro:~ kirito$ docker run --name box1 -it --rm busybox sh
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:07
          inet addr:172.17.0.7  Bcast:172.17.255.255  Mask:255.255.0.0

—rm 指令可以讓我們在退出容器時自動銷燬該容器,這樣便於測試。檢視自身的 ip 為 172.17.0.7,接下來建立第二個容器 box2。

kiritodeMacBook-Pro:~ kirito$ docker run --name box2 -it --rm busybox sh
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:08
          inet addr:172.17.0.8  Bcast:172.17.255.255  Mask:255.255.0.0

檢視自身的 ip 為 172.17.0.8。

在 box2 中執行 ping 命令測試與 box1 的連通性:

使用 IP
/ # ping 172.17.0.8
PING 172.17.0.8 (172.17.0.8): 56 data bytes
64 bytes from 172.17.0.8: seq=0 ttl=64 time=0.107 ms
64 bytes from 172.17.0.8: seq=1 ttl=64 time=0.116 ms
64 bytes from 172.17.0.8: seq=2 ttl=64 time=0.114 ms
64 bytes from 172.17.0.8: seq=3 ttl=64 time=0.126 ms

使用容器名稱
/ # ping box1
無響應

我們發現使用預設網橋 docker0 的橋接模式下,ip 是通的,但是無法使用容器名作為通訊的 host。

使用自定義網橋 my-net

kiritodeMacBook-Pro:~ kirito$ docker run --name box3 -it --rm  --network my-net busybox sh
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:15:00:02
          inet addr:172.21.0.2  Bcast:172.21.255.255  Mask:255.255.0.0

使用 —network 指定使用的網路模式,my-net 便是在此之前我們通過 docker network create 命令新建立的網路。新啟動一個 shell 建立 box4

kiritodeMacBook-Pro:~ kirito$ docker run -it --name box4 --rm --network my-net busybox sh
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:15:00:03
          inet addr:172.21.0.3  Bcast:172.21.255.255  Mask:255.255.0.0

在 box4 中執行 ping 命令測試與 box3 的連通性:

使用 IP
/ # ping 172.21.0.2
PING 172.21.0.2 (172.21.0.2): 56 data bytes
64 bytes from 172.21.0.2: seq=0 ttl=64 time=0.203 ms
64 bytes from 172.21.0.2: seq=1 ttl=64 time=0.167 ms
64 bytes from 172.21.0.2: seq=2 ttl=64 time=0.169 ms
64 bytes from 172.21.0.2: seq=3 ttl=64 time=0.167 ms

使用容器名稱
/ # ping box3
PING box3 (172.21.0.2): 56 data bytes
64 bytes from 172.21.0.2: seq=0 ttl=64 time=0.229 ms
64 bytes from 172.21.0.2: seq=1 ttl=64 time=0.170 ms
64 bytes from 172.21.0.2: seq=2 ttl=64 time=0.165 ms
64 bytes from 172.21.0.2: seq=3 ttl=64 time=0.168 ms

與預設的網路 docker0 不同的是,指定了自定義 network 的容器可以使用容器名稱相互通訊,實際上這也是 docker 官方推薦使用 —network 引數執行容器的原因之一。

對比自定義 bridge(my-net)與預設 bridge(docker0)

自定義 bridge 提供更好的隔離性和容器間的互操作性

連線到同一個自定義 bridge 網路的容器會自動將所有埠相互暴露,並且無法連線到容器之外的網路。這使得容器化的應用能輕鬆地相互通訊,並且與外部環境產生了良好的隔離性。

例如一個包含了 web 應用,資料庫,redis 等元件的應用程式。很有可能只希望對外界暴露 80 埠,而不允許外界訪問資料庫埠和 redis 埠,而又不至於讓 web 應用本身無法訪問資料庫和 redis, 便可以使用自定義 bridge 網路輕鬆實現。如果在預設 bridge 網路上執行相同的應用程式,則需要使用 -p 或 —publish 標誌開啟 web 埠,資料庫埠,redis 埠。這意味著 Docker 宿主機需要通過其他方式阻止對資料庫埠,redis 埠的訪問,無意增大了工作量。

自定義 bridge 提供容器間的自動 DNS 解析

這一點在上一節的實驗中已經驗證過了。預設 bridge 網路上的容器只能通過 IP 地址互相訪問,除非使用在 docker run 時新增 —link 引數。這麼做個人認為有兩點不好的地方:

  1. 容器關係只要稍微複雜一些,便會對管理產生不便。

  2. —link 引數在官方文件中已經被標記為過期的引數,不被建議使用。

在使用者定義的橋接網路上,容器可以通過容器名稱(--name 指定的名稱)或別名來解析對方。可能有人說,在預設 bridge 模式下我可以去修改 /etc/hosts檔案呀,但這顯然不是合理的做法。

容器可以在執行中與自定義 bridge 網路連線和分離

在容器的生命週期中,可以在執行中將其與自定義網路連線或斷開連線。 而要從預設 bridge 網路中移除容器,則需要停止容器並使用不同的網路選項重新建立容器。

每個自定義的 bridge 網路都會建立一個可配置的網橋

如果容器使用預設 bridge 網路,雖然可以對其進行配置,但所有容器都使用相同的預設設定,例如 MTU 和防火牆規則。另外,配置預設 bridge 網路隔離於 Docker 本身之外,並且需要重新啟動 Docker 才可以生效。

自定義的 bridge 是使用 docker network create 建立和配置的。如果不同的應用程式組具有不同的網路要求,則可以在建立時分別配置每個使用者定義的 bridge 網路,這無疑增加了靈活性和可控性。

使用預設 bridge 容器共享所有的環境變數

在 Docker 的舊版本中,兩個容器之間共享環境變數的唯一方法是使用 —link 標誌來進行連結。這種型別的變數共享對於自定義的網路是不存在的。但是,自定義網路有更好方式來實現共享環境變數:

  • 多個容器可以使用 Docker 捲來掛載包含共享資訊的檔案或目錄。
  • 多個容器可以使用 docker-compose 一起啟動,並且 docker-compose.yml 檔案可以定義共享變數。
  • 使用叢集服務而不是獨立容器,並利用共享金鑰和配置。

結合上述這些論述和官方文件的建議,使用 bridge 網路驅動模式時,最好新增使用 —network 來指定自定義的網路。


原文連結