目錄:
- Docker 為什么需要網絡管理
- Docker 網絡架構簡介
- CNM
- Libnetwork
- 驅動
- 常見網絡類型
- bridge 網絡
- host 網絡
- container 網絡
- none 網絡
- overlay 網絡
- docker 網絡管理命令
- docker network create
- docker network inspect
- docker network connect
- docker network disconnect
- docker network prune
- docker network rm
- docker network ls
- 網絡命令基本操作
- 網絡詳解
- docker Bridge 網絡
- 網絡介紹
- 生活案例
- 操作案例
- 容器間的網絡通信
- 創建自定義 bridge
- DNS 解析
- 端口暴露和轉發
- docker Host 網絡
- 網絡介紹
- 操作案例
- docker Container 網絡
- 網絡介紹
- 操作案例
- docker Bridge 網絡
- docker none 網絡
- 網絡介紹
- 操作案例
1.Docker 為什么需要網絡管理
容器的網絡默認與宿主機及其他容器都是相互隔離, 但同時我們也要考慮下面的一些問題, 比如
- 多個容器之間是如何通信的
- 容器和宿主機是如何通信的
- 容器和外界主機是如何通信的
- 容器中要運行一些網絡應用(如 nginx、 web 應用、數據庫等),如果要讓外部也可以訪問這些容器內運行的網絡應用應該如何實現
- 容器不想讓它的網絡與宿主機、與其他容器隔離應該如何實現
- 容器根本不需要網絡的時候應該如何實現
- 容器需要更高的定制化網絡(如定制特殊的集群網絡、定制容器間的局域網)應該如何實現
上述的這些問題都需要我們對容器的網絡進行合理的管理才能解決,這就體現出了容器網絡管理的重要性。
?
2.Docker 網絡架構簡介
Docker 容器網絡是為應用程序所創造的虛擬環境的一部分,它能讓應用從宿主機操作系統的網絡環境中獨立出來,形成容器自有的網絡設備、 IP 協議棧、端口套接字、 IP路由表、防火墻等等與網絡相關的模塊。Docker 為實現容器網絡,主要采用的架構由三部分組成: CNM、 Libnetwork 和驅動。
CNM
Docker 網絡架構采用的設計規范是 CNM(Container Network Model)。 CNM 中規定了 Docker 網絡的基礎組成要素: Sandbox、 Endpoint、 Network。
- Sandbox:提供了容器的虛擬網絡棧,也即端口、套接字、 IP 路由表、防火墻、DNS 配置等內容。主要用于隔離容器網絡與宿主機網絡,形成了完全獨立的容器網絡環境。
- Network: Docker 內部的虛擬子網,使得網絡內的參與者能夠進行通訊。
- Endpoint:就是虛擬網絡的接口,就像普通網絡接口一樣, Endpoint 的主要職責是負責創建連接。 Endpoint 類似于常見的網絡適配器,那也就意味著一個 Endpoint 只能接入某一個網絡, 當容器需要接入到多個網絡,就需要多個 Endpoint。
- 如上圖所示,容器 B 有兩個 Endpoint 并且分別接入 Networkd A 和 Network B。那么容器 A 和容器 B 之間是可以實現通信的,因為都接入了 NetworkA。但是容器 A 和容器 C 不可以通過容器 B 的兩個 Endpoint 通信。
Libnetwork
Libnetwork 是 CNM 的一個標準實現。 Libnetwork 是開源庫,采用 Go 語言編寫(跨平臺的),也是 Docker 所使用的庫, Docker 網絡架構的核心代碼都在這個庫中。Libnetwork 實現了 CNM 中定義的全部三個組件,此外它還實現了本地服務發現、基于 Ingress 的容器負載均衡,以及網絡控制層和管理層等功能。
驅動
驅動主要負責實現數據層相關內容,例如網絡的連通性和隔離性是由驅動來處理的。驅動通過實現特定網絡類型的方式擴展了 Docker 網絡棧,例如橋接網絡和覆蓋網絡。Docker 內置了若干驅動,通常被稱作原生驅動或者本地驅動。例如 Bridge Driver、Host Driver、 Overlay Driver、 MacVLan Driver、 IPVLan Driver、 None Driver 等等。每個驅動負責創建其上所有網絡資源的創建和管理。
3.常見網絡類型
bridge 網絡
bridge 驅動會在 Docker 管理的主機上創建一個 Linux 網橋。默認情況下,網橋上的容器可以相互通信。也可以通過 bridge 驅動程序配置,實現對外部容器的訪問。Docker 容器的默認網絡驅動.當我們需要多個容器在同一個 Docker 主機上通信時,橋接網絡是最佳選擇。
host 網絡
對于獨立容器,移除容器和 Docker 主機之間的網絡隔離,并直接使用主機的網絡。當網絡堆棧不應該與 Docker 主機隔離,但是希望容器的其他資源被隔離時,主機網絡是最佳選擇。
?
container 網絡
這個模式指定新創建的容器和引進存在的一個容器共享一個網絡 ,而不是和宿主機共享。新創建的容器不會創建自己的網卡,配置自己的 ip,而是和一個指定的容器共享 ip,端口等,兩個容器除了網絡方面,其他的如文件系統、進程列表等還是隔離的。兩個容器的進程可以通過 lo 網卡設備通信
none 網絡
Docker 容器擁有自己的 Network Namespace,但是,并不為 Docker 容器進行任何網絡配置。也就是說,這個 Docker 容器沒有網卡、 IP、路由等信息。容器完全網絡隔離。
overlay 網絡
借助 Docker 集群模塊 Docker Swarm 搭建的跨 Docker Daemon 網絡。將多個Docker 守護進程連接在一起,使集群服務能夠相互通信。當我們需要運行在不同Docker 主機上的容器進行通信時,或者當多個應用程序使用集群服務協同工作時,覆蓋網絡是最佳選擇。
另外,在 Docker 安裝時,會自動安裝一塊 Docker 網卡稱為 docker0,它是一個網橋設備,主要用于 Docker 各容器及宿主機的網絡通信。
?
4.docker 網絡管理命令
命令清單
docker network create
功能
創建自定義網絡
語法
?
關鍵參數
- -d, --driver: 網絡驅動
- --gateway: 網關地址
- --subnet: 表示網段的 CIDR 格式的子網
- --ipv6: 啟用 ipv6
樣例
docker network inspect
功能
查看網絡詳情
語法
關鍵參數
-f,--format:指定格式
樣例
?
docker network connect
功能
于將容器連接到網絡。可以按名稱或 ID 連接容器。 一旦連接,容器可以與同一網絡中的其他容器通信。
語法
關鍵參數
--ip: 指定 IP 地址
--ip6: 指定 IPv6 地址
樣例
?
docker network disconnect
功能
斷開網絡
語法
關鍵參數
-f:強制退出
樣例
docker network prune
功能
刪除不使用的網絡
語法
?
關鍵參數
-f, --force : 不提示
樣例
docker network rm
功能
刪除 1 個或者多個網絡
語法
關鍵參數
-f:強制退出
樣例
?
?docker network ls
功能
列出網絡
語法
別名
?
關鍵參數
- -f, --filter:指定過濾條件
- --format:指定格式
- --no-trunc:不截斷
- -q, --quiet :僅僅顯示 id
樣例
?
網絡命令基本操作
創建網絡并指定 ip 地址段
查看創建的網絡
創建一個容器并加入網絡
查看容器網絡信息
創建一個新的 nginx 容器 mynginx2,但是不加入我們的自定義網絡
查看該容器的網絡配置,可以看到采用的是 docker0 橋
?
?
我們將該容器加入到我們自己創建的網絡
?
再次查看我們的容器 2 的網絡配置,可以 看到它多了一個 mynetwork
?
?
我們讓容器二斷開網絡
?
再次查看容器 2 網絡配置,可以看到只有 1 個 bridge 網絡了
?
刪除網絡,可以看到網絡被使用了,無法刪除
?
再次刪除容器,刪除網絡,可以看到只要我們停止了所有容器,就可以正常的刪除網絡了。
?
5.網絡詳解
docker Bridge 網絡
網絡介紹
Docker Bridge 網絡采用內置的 bridge 驅動, bridge 驅動底層采用的是 Linux 內核中Linux bridge 技術。就網絡而言, bridge 網絡是在網絡段之間轉發流量的鏈路層設備,而網橋可以是在主機內核中運行的硬件設備或軟件設備;就 Docker 而言,橋接網絡使用軟件網橋 docker0,它允許連接到同一網橋網絡的容器進行通信,同時提供與未連接到該網橋網絡容器的隔離。Docker Container 的 bridge 橋接模式可以參考下圖
默認情況下,創建的容器在沒有使用--network 參數指定要加入的 docker 網絡時,默認都是加入 Docker 默認的單機橋接網絡,即下面的 name 為 bridge 的網絡。
?
默認的 bridge 網絡會被映射到內核中為 docker0 的網橋上。Docker 默認的 bridge 網絡和 Linux 內核中的 docker0 網橋是一一對應的關系。bridge 是 Docker 對網絡的命名,而 docker0 是內核中網橋的名字。
?
生活案例?
bridge 就像一個立交橋一樣,有很多條路可以四通八達,每條路都連接了 2 個方向的通道。
操作案例
容器間的網絡通信
回憶一下之前學到網絡知識:多臺主機是如何通過網絡中進行通信的?
如果是兩臺主機可以直接通過連接網線的兩端進行通信。那多臺主機通信怎么處理呢?這就需要新增路由器/交換機,把多臺主機連接到路由器/交換機上, 通過路由器/交換機來達到交換數據, 即通信的目的。
其實容器之間的通信也和上面主機通信的方式如出一轍, 之前我們提到了安裝 Docker的時候會默認 docker0 這個網橋軟件設備, 這個 docker0 設備可以類比成上圖的交換機/路由器設備,當我們創建好容器之后, 如果不手動指定網絡模式,默認會使用bridge 網絡, 容器會自動連接到 docker0 這個網橋設備, 然后通過這個網橋來進行容器間的通信。下面我們一起來做個實驗驗證一下.
使用 busybox 鏡像創建兩個容器, 并且保持在后臺運行
?
關于 BusyBox 鏡像介紹:
BusyBox 是一個集成了一百多個最常用 Linux 命令和工具(如 cat、 echo、grep、 mount、 telnet 等)的精簡工具箱,它只需要幾 MB 的大小,很方便進行各種快速驗證,被譽為“Linux 系統的瑞士軍刀”。BusyBox 可運行于多款 POSIX 環境的操作系統中,如 Linux(包括Android)、 Hurd、 FreeBSD 等先看一下兩個容器間通信的現象
?
確定兩個容器可以通信之后, 我們來查看一下 bridge 網絡的信息
此時, 該網絡已經連接了兩個容器,即 c1 和 c2。c1 和 c2 兩個容器就是通過 docker0 這個網橋來進行通信的。當我們停止或刪除掉一個容器的時候, 會發現該容器會自動和 docker0 切斷連接
?
?
創建自定義 bridge
在默認情況下, 我們創建的容器都會連接在 docker0 這個 bridge 上。那其實我們也可以創建一些自定義的 bridge,讓運行的容器通過自定義 bridge 進行通信。可以通過 create 命令來創建新的 bridge.
-d,--driver 選項指定網絡驅動程序
在創建自定義 bridge 的時候可能會出現如下報錯
?
我們可以通過重啟 docker 服務來解決這個問題
?
使用命令 docker network inspect 查看 new-bridge 網絡信息會發現這個網絡的子網 IP 是 172.18.0.0/16, 它表示如果我們創建容器并連接到該網絡上, 就會給該容器分配一個 172.18.xx.xx 這個網段的 IP 地址。
?
那我們在創建容器的時候, 怎么才能連接自定義的這個 bridge 呢?可以通過--network 選項指定要連接的網絡, 如果不指定, 默認是連接的 bridge。
查看自定義 bridge 網絡的詳細信息, 發現 c3 容器已經連接到該網絡上了。
DNS 解析
Docker 自定義橋接網絡是支持通過 Docker DNS 服務進行域名解析的, 也就是說我們可以直接使用容器名進行通信,因為 DNS 服務可以解析容器名到 IP 地址的映射, 但是默認的 bridge 網絡是不支持 DNS 的。?
準備實驗環境: c1 和 c2 容器默認連接 bridge 網絡, c3 和 c4 容器默認連接 newbridge 網絡
?
驗證 c1 和 c2 是否能夠使用 dns 解析服務
?
驗證 c3 和 c4 是否能夠使用 DNS 解析服務
?
端口暴露和轉發
暴露方式
端口暴露有 2 種方式,在啟動容器的時候添加端口參數,一種-P 暴露所有端口,一種
是-p,暴露指定端口
-p
將指定的容器端口映射至主機所有地址的一個動態端口, ·“動態端口”指隨機端口,具體的映射結果可使用 docker port 命令查看
-p <hostPort>:<containerPort>
將容器端口<containerPort>映射至指定的主機端口<hostPort>
端口轉發
連接 bridge 網絡的容器只能與連接在當前網絡中的容器進行通信。如果一個容器想要對外提供一些網絡服務的話,需要進行端口轉發才可以實現。端口轉發將 Docker 容器的端口映射到宿主機的端口上,那么任何發送到宿主機該端口的流量,都會被轉發到容器的端口中。如下圖所示,兩個容器內部均開放 80 端口,它們分別映射到宿主機的 8088 和 8089 端口, 即表示任何發送到 8088 端口的流量都會轉發到 Container 1 容器的 80 端口, 發送到 8089 端口的流程都會轉發到Container 2 容器的 80 端口。
我們啟動一個容器,配置 80 端口的轉發:
?--rm 表示運行完自動刪除該容器
--name 指定容器名
當我們通過 web 瀏覽器訪問宿主機的 8088 端口時,會得到 nginx 主頁
?
docker Host 網絡
網絡介紹
Docker 容器運行默認都會分配獨立的 Network Namespace 隔離子系統, 但是如果基于 host 網絡模式,容器將不會獲得一個獨立的 Network Namespace,而是和宿主機共用同一個 Network Namespace,容器將不會虛擬出自己的網卡, IP 等,而是直接使用宿主機的 IP 和端口。
連接到 host 網絡的容器共享宿主機的網絡棧,容器的網絡配置與宿主機完全一樣。我們可以通過 --network=host 指定使用 host 網絡。
操作案例
下面我們一起來動手操作一下
可以看到 c1 容器是獨立的網絡配置, 而 c2 容器是和宿主機共享網絡配置。
使用場景
- 之前我們提到 bridge 網絡在通信的時候需要進行端口轉發以及 NAT 地址轉換,這勢必會消耗掉一些資源以及性能。
- 那么直接使用 host 網絡最大的好處就是性能好,如果容器對網絡傳輸效率有較高的要求,建議選擇 host 網絡。當然也會犧牲一些東西,比如要考慮端口沖突問題,其他服務已經被占用的端口就不能再使用了。
docker Container 網絡
網絡介紹
Docker Container 的 other container 網絡模式是 Docker 中一種較為特別的網絡的模式。之所以稱為“other container 模式”,是因為這個模式下的 Docker Container,會使用其他容器的網絡環境。之所以稱為“特別”,是因為這個模式下容器的網絡隔離性會處于 bridge 橋接模式與 host 模式之間。 Docker Container 共享其他容器的網絡環境,則至少這兩個容器之間不存在網絡隔離,而這兩個容器又與宿主機以及除此之外其他的容器存在網絡隔離。Docker Container 的 other container 網絡模式可以參考下圖:
Docker Container 的 other container 網絡模式實現邏輯如下:
- 查找 other container(即需要被共享網絡環境的容器)的網絡 namespace;
- 將新創建的 Docker Container(也是需要共享其他網絡的容器)的 namespace,使用 other container 的 namespace
操作案例
創建一個 busybox 容器
使用 netcontainer1 的網絡創建另外一個容器
?
進入兩個容器,查看容器的 ip 信息,發現兩個 ip 和 mac 完全一樣
?
我們停止容器 1,再次看下容器 2 的網絡,發現 eth0 網卡消失了,只有一個本地網絡了
我們再次重啟容器 1 和容器 2
再次查看,然后可以看到容器網絡恢復
?
使用場景
在這種模式下的 Docker Container 可以通過 localhost 來訪問 namespace 下的其他容器,傳輸效率較高。但是兩個容器之間存在依賴,如果依賴容器重啟了,會導致另外一個服務的網絡不可用。
?
docker none 網絡
網絡介紹
none 網絡就是指沒有網絡。掛在這個網絡下的容器除了 lo(本地回環),沒有其他任何網卡。
操作案例
在運行容器的時候,可以通過--network=none 參數來指定容器使用 none 網絡。
使用場景
- 針對一些對安全性要求比較高并且不需要聯網的應用, 可以使用 none 網絡, 比如生成隨機密碼, 避免生成密碼被第三方獲取。
- 一些第三方的應用可能需要 docker 幫忙創建一個沒有網絡的容器, 網絡由第三方自己來配置。
?