Docker網路模式詳解及容器間網路通訊(6)
Docker網路模式詳解及容器間網路通訊
參考資料
1. 預設網路
安裝 Docker 以後,會預設建立三種網路,可以通過 docker network ls 檢視。
[root@CentOS7 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 71c1c4608319 bridge bridge local 767f114c1d6a host host local 239984d23cb5 none null local
在學習 Docker 網路之前,我們有必要先來了解一下這幾種網路模式都是什麼意思。
網路模式 | 簡介 |
---|---|
bridge | 為每一個容器分配、設定 IP 等,並將容器連線到一個 docker0 虛擬網橋,預設為該模式。 |
host | 容器將不會虛擬出自己的網絡卡,配置自己的 IP 等,而是使用宿主機的 IP 和埠。 |
none | 容器有獨立的 Network namespace,但並沒有對其進行任何網路設定,如分配 veth pair 和網橋連線,IP 等。 |
container | 新建立的容器不會建立自己的網絡卡和配置自己的 IP,而是和一個指定的容器共享 IP、埠範圍等。 |
1.1. bridge網路模式
在該模式中,Docker 守護程序建立了一個虛擬乙太網橋 docker0 ,新建的容器會自動橋接到這個介面,附加在其上的任何網絡卡之間都能自動轉發資料包。
預設情況下,守護程序會建立一對對等虛擬裝置介面 veth pair ,將其中一個介面設定為容器的 eth0 介面(容器的網絡卡),另一個介面放置在宿主機的名稱空間中,以類似 vethxxx 這樣的名字命名,從而將宿主機上的所有容器都連線到這個內部網路上。
比如我執行一個基於 busybox 映象構建的容器 bbox01 ,檢視 ip addr :
busybox 被稱為嵌入式 Linux 的瑞士軍刀,整合了很多小的 unix 下的通用功能到一個小的可執行檔案中。
然後宿主機通過 ip addr 檢視資訊如下:
通過以上的比較可以發現,證實了之前所說的:守護程序會建立一對對等虛擬 裝置介面 veth pair ,將其中一個介面設定為容器的 eth0 介面(容器的網 卡),另一個介面放置在宿主機的名稱空間中,以類似 vethxxx 這樣的名字命名。
同時,守護程序還會從網橋 docker0 的私有地址空間中分配一個 IP 地址和子 網給該容器,並設定 docker0 的 IP 地址為容器的預設閘道器。也可以安裝 yum install -y bridge-utils 以後,通過 brctl show 命令檢視網橋資訊。
對於每個容器的 IP 地址和 Gateway 資訊,我們可以通過 docker inspect 容器名稱|ID 進行檢視,在 NetworkSettings 節點中可以看到詳細資訊。
我們可以通過 docker network inspect bridge 檢視所有 bridge 網路模 式下的容器,在 Containers 節點中可以看到容器名稱。
關於 bridge 網路模式的使用,只需要在建立容器時通過引數 --net bridge 或者 --network bridge 指定即可,當然這也是建立容器預設使用的 網路模式,也就是說這個引數是可以省略的。
Bridge 橋接模式的實現步驟主要如下:
- Docker Daemon 利用 veth pair 技術,在宿主機上建立一對對等虛擬網路介面設 備,假設為 veth0 和 veth1。而 veth pair 技術的特性可以保證無論哪一個 veth 接收到網路報文,都會將報文傳 輸給另一方。
- Docker Daemon 將 veth0 附加到 Docker Daemon 建立的 docker0 網橋上。保證宿 主機的網路報文可以發往 veth0;
- Docker Daemon 將 veth1 新增到 Docker Container 所屬的 namespace 下,並被改 名為 eth0。如此一來,宿主機的網路報文若發往 veth0,則立即會被 Container 的 eth0 接收,實現宿主機到 Docker Container 網路的聯通性;同時,也保證 Docker Container 單獨使用 eth0,實現容器網路環境的隔離性。
1.2. host網路模式
- host 網路模式需要在建立容器時通過引數 --net host 或者 --network host 指定;
- 採用 host 網路模式的 Docker Container,可以直接使用宿主機的 IP 地址與外界進 行通訊,若宿主機的 eth0 是一個公有 IP,那麼容器也擁有這個公有 IP。同時容 器內服務的埠也可以使用宿主機的埠,無需額外進行 NAT 轉換;
- host 網路模式可以讓容器共享宿主機網路棧,這樣的好處是外部主機與容器直 接通訊,但是容器的網路缺少隔離性。
比如我基於 host 網路模式建立了一個基於 busybox 映象構建的容器 bbox02 ,檢視 ip addr :
然後宿主機通過 ip addr 檢視資訊如下:
對,你沒有看錯,返回資訊一模一樣,我也可以肯定我沒有截錯圖,不信接著 往下看。我們可以通過 docker network inspect host 檢視所有 host 網路模 式下的容器,在 Containers 節點中可以看到容器名稱。
1.3. none網路模式
- none 網路模式是指禁用網路功能,只有 lo 介面 local 的簡寫,代表 127.0.0.1,即 localhost 本地環回介面。在建立容器時通過引數 --net none 或者 --network none 指定;
- none 網路模式即不為 Docker Container 建立任何的網路環境,容器內部就只能 使用 loopback 網路裝置,不會再有其他的網路資源。可以說 none 模式為 Docke Container 做了極少的網路設定,但是俗話說得好“少即是多”,在沒有網路配置 的情況下,作為 Docker 開發者,才能在這基礎做其他無限多可能的網路定製開 發。這也恰巧體現了 Docker 設計理念的開放。
比如我基於 none 網路模式建立了一個基於 busybox 映象構建的容器 bbox03 ,檢視 ip addr :
我們可以通過 docker network inspect none 檢視所有 none 網路模式下 的容器,在 Containers 節點中可以看到容器名稱。
1.4. container網路模式
- Container 網路模式是 Docker 中一種較為特別的網路的模式。在建立容器時通過 引數 --net container:已執行的容器名稱|ID 或者 --network container:已 執行的容器名稱|ID 指定;
- 處於這個模式下的 Docker 容器會共享一個網路棧,這樣兩個容器之間可以使用 localhost 高效快速通訊。
Container 網路模式即新建立的容器不會建立自己的網絡卡,配置自己的 IP,而是 和一個指定的容器共享 IP、埠範圍等。同樣兩個容器除了網路方面相同之外,其他的如檔案系統、程序列表等還是隔離的。
比如我基於容器 bbox01 建立了 container 網路模式的容器 bbox04 ,檢視 ip addr :
容器 bbox01 的 ip addr 資訊如下:
宿主機的 ip addr 資訊如下:
通過以上測試可以發現,Docker 守護程序只建立了一對對等虛擬裝置介面用於 連線 bbox01 容器和宿主機,而 bbox04 容器則直接使用了 bbox01 容器的網絡卡資訊。
這個時候如果將 bbox01 容器停止,會發現 bbox04 容器就只剩下 lo 介面了。
然後 bbox01 容器重啟以後,bbox04 容器也重啟一下,就又可以獲取到網絡卡信 息了。
1.5 link
docker run --link 可以用來連線兩個容器,使得源容器(被連結的容器)和 接收容器(主動去連結的容器)之間可以互相通訊,並且接收容器可以獲取源容器 的一些資料,如源容器的環境變數。
這種方式官方已不推薦使用,並且在未來版本可能會被移除,所以這裡不作為 重點講解,感興趣可自行了解。
官網警告資訊:https://docs.docker.com/network/links/
2. 自定義網路
雖然 Docker 提供的預設網路使用比較簡單,但是為了保證各容器中應用的安全 性,在實際開發中更推薦使用自定義的網路進行容器管理,以及啟用容器名稱到 IP 地址的自動 DNS 解析。
從 Docker 1.10 版本開始,docker daemon 實現了一個內嵌的 DNS server, 使容器可以直接通過容器名稱進行通訊。方法很簡單,只要在建立容器時使用 --name 為容器命名即可。
但是使用 Docker DNS 有個限制:只能在 user-defined 網路中使用。也就是 說,預設的 bridge 網路是無法使用 DNS 的,所以我們就需要自定義網路。
2.1. 建立網路
通過 docker network create 命令可以建立自定義網路模式,命令提示如下:
進一步檢視 docker network create 命令使用詳情,發現可以通過 -- driver 指定網路模式且預設是 bridge 網路模式,提示如下:
建立命令:
# 建立一個基於 **bridge** 網路模式的自定義網路模式 custom_network ,完整命 令如下:
docker network create custom_network
# 通過 docker network ls 檢視網路模式:
docker network ls
# 通過自定義網路模式 custom_network 建立容器:
docker run -di --name bbox05 --net custom_network busybox
通過 docker inspect 容器名稱|ID 檢視容器的網路資訊,在 NetworkSettings 節點中可以看到詳細資訊。
2.2. 連線網路
通過 docker network connect 網路名稱 容器名稱 為容器連線新的網路模式。
# bbox05 連線到 bridge 網路
docker network connect bridge bbox05
# 檢視容器的網路資訊
docker inspect bbox05
通過 docker inspect 容器名稱|ID 再次檢視容器的網路資訊,多增加了預設的 bridge 。
2.3 斷開網路
# 通過 docker network disconnect 網路名稱 容器名稱 命令斷開網路。
docker network disconnect custom_network bbox05
# 通過 docker inspect 容器名稱|ID 再次檢視容器的網路資訊,發現只剩下預設的 bridge
docker inspect bbox05
2.4. 移除網路
可以通過 docker network rm 網路名稱 命令移除自定義網路模式,網路模式移除成功會返回網路模式名稱。
docker network rm custom_network
注意:如果通過某個自定義網路模式建立了容器,則該網路模式無法刪除
3. 容器間網路通訊
接下來我們通過所學的知識實現容器間的網路通訊。首先明確一點,容器之間要互相通訊,必須要有屬於同一個網路的網絡卡。
3.1. 預設網路通訊
# 我們先建立兩個基於預設的 bridge 網路模式的容器。
docker run -di --name default_bbox01 busybox
docker run -di --name default_bbox02 busybox
# 通過 docker network inspect bridge 檢視兩個容器的具體IP資訊
然後測試兩容器間是否可以進行網路通訊。
經過測試,從結果得知兩個屬於同一個網路的容器是可以進行網路通訊的,但 是 IP 地址可能是不固定的,有被更改的情況發生,那容器內所有通訊的 IP 地址也需要進行更改,能否使用容器名稱進行網路通訊?繼續測試。
經過測試,從結果得知使用容器進行網路通訊是不行的,那怎麼實現這個功能呢?
3.2. 自定義網路通訊
從 Docker 1.10 版本開始,docker daemon 實現了一個內嵌的 DNS server,使容 器可以直接通過容器名稱通訊。方法很簡單,只要在建立容器時使用 --name 為容器 命名即可。
但是使用 Docker DNS 有個限制:只能在 user-defined 網路中使用。也就是說, 預設的 bridge 網路是無法使用 DNS 的,所以我們就需要自定義網路。
我們先基於 bridge 網路模式建立自定義網路 custom_network ,然後建立兩 個基於自定義網路模式的容器。
docker run -di --name custom_bbox01 --net custom_network busybox
docker run -di --name custom_bbox02 --net custom_network busybox
通過 docker network inspect custom_network 檢視兩容器的具體 IP 信 息。
然後測試兩容器間是否可以進行網路通訊,分別使用具體 IP 和容器名稱進行網路通訊。
經過測試,從結果得知兩個屬於同一個自定義網路的容器是可以進行網路通訊 的,並且可以使用容器名稱進行網路通訊。
那如果此時我希望 bridge 網路下的容器可以和 custom_network 網路下的容器進行網路又該如何操作?其實答案也非常簡單:讓 bridge 網路下的容器連線至新的 custom_network 網路即可。
docker network connect custom_network default_bbox01
然後通過 default_bbox01 去 ping custom
學完容器網路通訊,大家就可以練習使用多個容器完成常見應用叢集的部署 了。後面就該學習 Docker 進階部分的內容 Docker Compose 和 Docker Swarm。