Docker 網絡模式詳解及容器間網絡通訊

  當項目大規模使用 Docker 時,容器通訊的問題也就產生了。要解決容器通訊問題,必須先了解不少關於網絡的知識。Docker 做爲目前最火的輕量級容器技術,有不少使人稱道的功能,如 Docker 的鏡像管理。然而,Docker 一樣有着不少不完善的地方,網絡方面就是 Docker 比較薄弱的部分。所以,咱們有必要深刻了解 Docker 的網絡知識,以知足更高的網絡需求。docker

  

默認網絡

  

  安裝 Docker 之後,會默認建立三種網絡,能夠經過 docker network ls 查看。shell

[root@localhost ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
688d1970f72e        bridge              bridge              local
885da101da7d        host                host                local
f4f1b3cf1b7f        none                null                local

  

  在學習 Docker 網絡以前,咱們有必要先來了解一下這幾種網絡模式都是什麼意思。安全

網絡模式 簡介
bridge 爲每個容器分配、設置 IP 等,並將容器鏈接到一個 docker0 虛擬網橋,默認爲該模式。
host 容器將不會虛擬出本身的網卡,配置本身的 IP 等,而是使用宿主機的 IP 和端口。
none 容器有獨立的 Network namespace,但並無對其進行任何網絡設置,如分配 veth pair 和網橋鏈接,IP 等。
container 新建立的容器不會建立本身的網卡和配置本身的 IP,而是和一個指定的容器共享 IP、端口範圍等。

  

bridge 網絡模式

  

  在該模式中,Docker 守護進程建立了一個虛擬以太網橋 docker0,新建的容器會自動橋接到這個接口,附加在其上的任何網卡之間都能自動轉發數據包。網絡

  默認狀況下,守護進程會建立一對對等虛擬設備接口 veth pair,將其中一個接口設置爲容器的 eth0 接口(容器的網卡),另外一個接口放置在宿主機的命名空間中,以相似 vethxxx 這樣的名字命名,從而將宿主機上的全部容器都鏈接到這個內部網絡上。oop

  好比我運行一個基於 busybox 鏡像構建的容器 bbox01,查看 ip addr學習

busybox 被稱爲嵌入式 Linux 的瑞士軍刀,整合了不少小的 unix 下的通用功能到一個小的可執行文件中。測試

  而後宿主機經過 ip addr 查看信息以下:spa

  經過以上的比較能夠發現,證明了以前所說的:守護進程會建立一對對等虛擬設備接口 veth pair,將其中一個接口設置爲容器的 eth0 接口(容器的網卡),另外一個接口放置在宿主機的命名空間中,以相似 vethxxx 這樣的名字命名。設計

  同時,守護進程還會從網橋 docker0 的私有地址空間中分配一個 IP 地址和子網給該容器,並設置 docker0 的 IP 地址爲容器的默認網關。也能夠安裝 yum install -y bridge-utils 之後,經過 brctl show 命令查看網橋信息。3d

  對於每一個容器的 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,實現容器網絡環境的隔離性。

  

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 節點中能夠看到容器名稱。

  

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 節點中能夠看到容器名稱。

  

container 網絡模式

  

  • Container 網絡模式是 Docker 中一種較爲特別的網絡的模式。在建立容器時經過參數 --net container:已運行的容器名稱|ID 或者 --network container:已運行的容器名稱|ID 指定;
  • 處於這個模式下的 Docker 容器會共享一個網絡棧,這樣兩個容器之間可使用 localhost 高效快速通訊。

  Container 網絡模式即新建立的容器不會建立本身的網卡,配置本身的 IP,而是和一個指定的容器共享 IP、端口範圍等。一樣兩個容器除了網絡方面相同以外,其餘的如文件系統、進程列表等仍是隔離的。

  

  好比我基於容器 bbox01 建立了 container 網絡模式的容器 bbox04,查看 ip addr

  容器 bbox01ip addr 信息以下:

  宿主機的 ip addr 信息以下:

  經過以上測試能夠發現,Docker 守護進程只建立了一對對等虛擬設備接口用於鏈接 bbox01 容器和宿主機,而 bbox04 容器則直接使用了 bbox01 容器的網卡信息。

  這個時候若是將 bbox01 容器中止,會發現 bbox04 容器就只剩下 lo 接口了。

  而後 bbox01 容器重啓之後,bbox04 容器也重啓一下,就又能夠獲取到網卡信息了。

  

link

  

  docker run --link 能夠用來連接兩個容器,使得源容器(被連接的容器)和接收容器(主動去連接的容器)之間能夠互相通訊,而且接收容器能夠獲取源容器的一些數據,如源容器的環境變量。

  這種方式官方已不推薦使用,而且在將來版本可能會被移除,因此這裏不做爲重點講解,感興趣可自行了解。

  官網警告信息:https://docs.docker.com/network/links/

  

自定義網絡

  

  雖然 Docker 提供的默認網絡使用比較簡單,可是爲了保證各容器中應用的安全性,在實際開發中更推薦使用自定義的網絡進行容器管理,以及啓用容器名稱到 IP 地址的自動 DNS 解析。

  從 Docker 1.10 版本開始,docker daemon 實現了一個內嵌的 DNS server,使容器能夠直接經過容器名稱通訊。方法很簡單,只要在建立容器時使用 --name 爲容器命名便可。

  可是使用 Docker DNS 有個限制:只能在 user-defined 網絡中使用。也就是說,默認的 bridge 網絡是沒法使用 DNS 的,因此咱們就須要自定義網絡。

  

建立網絡

  

  經過 docker network create 命令能夠建立自定義網絡模式,命令提示以下:

  

  進一步查看 docker network create 命令使用詳情,發現能夠經過 --driver 指定網絡模式且默認是 bridge 網絡模式,提示以下:

  

  建立一個基於 bridge 網絡模式的自定義網絡模式 custom_network,完整命令以下:

docker network create custom_network

  

  經過 docker network ls 查看網絡模式:

[root@localhost ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
b3634bbd8943        bridge              bridge              local
062082493d3a        custom_network      bridge              local
885da101da7d        host                host                local
f4f1b3cf1b7f        none                null                local

  

  經過自定義網絡模式 custom_network 建立容器:

docker run -di --name bbox05 --net custom_network busybox

  

  經過 docker inspect 容器名稱|ID 查看容器的網絡信息,在 NetworkSettings 節點中能夠看到詳細信息。

  

鏈接網絡

  

  經過 docker network connect 網絡名稱 容器名稱 爲容器鏈接新的網絡模式。

docker network connect bridge bbox05

  經過 docker inspect 容器名稱|ID 再次查看容器的網絡信息,多增長了默認的 bridge

  

斷開網絡

  

  經過 docker network disconnect 網絡名稱 容器名稱 命令斷開網絡。

docker network disconnect custom_network bbox05

  經過 docker inspect 容器名稱|ID 再次查看容器的網絡信息,發現只剩下默認的 bridge

  

移除網絡

  

  能夠經過 docker network rm 網絡名稱 命令移除自定義網絡模式,網絡模式移除成功會返回網絡模式名稱。

docker network rm custom_network

注意:若是經過某個自定義網絡模式建立了容器,則該網絡模式沒法刪除。

  

容器間網絡通訊

  

  接下來咱們經過所學的知識實現容器間的網絡通訊。首先明確一點,容器之間要互相通訊,必需要有屬於同一個網絡的網卡。

  咱們先建立兩個基於默認的 bridge 網絡模式的容器。

docker run -di --name default_bbox01 busybox
docker run -di --name default_bbox02 busybox

  

  經過 docker network inspect bridge 查看兩容器的具體 IP 信息。

  

  而後測試兩容器間是否能夠進行網絡通訊。

  

  通過測試,從結果得知兩個屬於同一個網絡的容器是能夠進行網絡通訊的,可是 IP 地址多是不固定的,有被更改的狀況發生,那容器內全部通訊的 IP 地址也須要進行更改,可否使用容器名稱進行網絡通訊?繼續測試。

  

  通過測試,從結果得知使用容器進行網絡通訊是不行的,那怎麼實現這個功能呢?

  從 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

學完容器網絡通訊,你們就能夠練習使用多個容器完成常見應用集羣的部署了。後面就該學習 Docker 進階部分的內容 Docker Compose 和 Docker Swarm。

本文采用 知識共享「署名-非商業性使用-禁止演繹 4.0 國際」許可協議

你們能夠經過 分類 查看更多關於 Docker 的文章。

  

🤗 您的點贊轉發是對我最大的支持。

📢 掃碼關注 哈嘍沃德先生「文檔 + 視頻」每篇文章都配有專門視頻講解,學習更輕鬆噢 ~

相關文章
相關標籤/搜索