當項目大規模使用 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
:
容器 bbox01
的 ip 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 國際」許可協議
。
🤗 您的點贊
和轉發
是對我最大的支持。
📢 掃碼關注 哈嘍沃德先生
「文檔 + 視頻」每篇文章都配有專門視頻講解,學習更輕鬆噢 ~