四、Docker 網絡原理、分類及容器互聯配置

本文是《Docker必知必會系列》第四篇,原文發佈於個人博客:悟塵紀

上一篇:Docker必知必會系列(三):基於 Docker-registry/Nexus3 搭建本地倉庫

Docker 網絡配置

Docker 網絡基本原理

要實現網絡通信,機器需要至少一個網絡接口(物理接口或虛擬接口)來收發數據包。如果不同子網之間要進行通信,需要路由機制。

Docker 中的網絡接口默認都是虛擬接口,虛擬接口的優勢之一是轉發效率較高。 Linux 通過在內核中進行數據複製來實現虛擬接口之間的數據轉發,發送接口的發送緩存中的數據包被直接複製到接收接口的接收緩存中。

當 Docker 啓動時,會自動在主機上創建一個 docker0 虛擬網橋( Linux 的一個 bridge),它會在掛載到它的網口之間進行轉發。同時,Docker 隨機分配一個本地未佔用的私有網段中的一個地址給 docker0 接口,此後啓動的容器內的網口也會自動分配一個同一網段(172.17.0.0/16)的地址。

當創建一個 Docker 容器的時候,同時會創建了一對 veth pair 接口(當數據包發送到一個接口時,另外一個接口也可以收到相同的數據包)。這對接口一端在容器內,即 eth0;另一端在本地並被掛載到 docker0 網橋,名稱以 veth 開頭(例如 vethAQI2QT)。通過這種方式,主機可以跟容器通信,容器之間也可以相互通信。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-EuyO1Yaw-1588987217143)(https://pic.lixl.cn/2020/network.png)]

關於 Docker 網絡的更多內容,可以訪問:https://docs.docker.com/network/>

Docker 網絡類型

Docker 創建一個容器的時候,會執行如下操作:

  • 創建一對虛擬接口,分別放到本地主機和新容器中;
  • 本地主機一端橋接到默認的 docker0 或指定網橋上,並具有一個唯一的名字,如 veth65f9;
  • 容器一端放到新容器中,並修改名字作爲 eth0,這個接口只在容器的命名空間可見;
  • 從網橋可用地址段中獲取一個空閒地址分配給容器的 eth0,並配置默認路由到橋接網卡 veth65f9。

完成這些之後,容器就可以使用 eth0 虛擬網卡來連接其他容器和其他網絡。

可以在 docker run 的時候通過 --net 參數來指定容器的網絡配置,有 4 個可選值:

  • --net=bridge 這個是默認值,連接到默認的網橋。
  • --net=host 告訴 Docker 不要將容器網絡放到隔離的命名空間中,即不要容器化容器內的網絡。此時容器使用本地主機的網絡,它擁有完全的本地主機接口訪問權限。容器進程可以跟主機其它 root 進程一樣可以打開低範圍的端口,可以訪問本地網絡服務比如 D-bus,還可以讓容器做一些影響整個主機系統的事情,比如重啓主機。因此使用這個選項的時候要非常小心。如果進一步的使用 --privileged=true,容器會被允許直接配置主機的網絡堆棧。
  • --net=container:NAME_or_ID 讓 Docker 將新建容器的進程放到一個已存在容器的網絡棧中,新容器進程有自己的文件系統、進程列表和資源限制,但會和已存在的容器共享 IP 地址和端口等網絡資源,兩者進程可以直接通過 lo 環回接口通信。
  • --net=none 讓 Docker 將新容器放到隔離的網絡棧中,但是不進行網絡配置。之後,用戶可以自己進行配置。

外部訪問容器

默認情況下,容器可以主動訪問到外部網絡的連接,但是外部網絡無法訪問到容器。想要允許外部訪問容器,可以在 docker run 時候通過 -p-P 參數來啓用(可以多次使用 -p 標記來綁定多個端口)。

使用 docker ps 可以看到,本地主機的 80 被映射到了容器的 80 端口。此時訪問本機的 80 端口即可訪問容器內 nginx 應用提供的界面。

docker ps
CONTAINER ID  IMAGE   COMMAND        CREATED        STATUS        PORTS               NAMES
bc533791f3f5  nginx   "nginx -g '…"  5 days ago     Up 4 days     0.0.0.0:80->80/tcp  nginx

容器間互聯

先創建一個新的 Docker 網絡:

docker network create -d bridge lixl-net
  • -d 參數指定 Docker 網絡類型,有 bridgeoverlay。其中 overlay 網絡類型用於 Swarm mode。

運行一個容器並連接到新建的 lixl-net 網絡

docker run -it --rm --name busybox1 --network lixl-net busybox sh

打開新的終端,再運行一個容器並加入到 lixl-net 網絡

docker run -it --rm --name busybox2 --network lixl-net busybox sh

再打開一個新的終端查看容器信息

docker ps

CONTAINER ID     IMAGE      COMMAND    CREATED            STATUS         PORTS     NAMES
b47060aca56b     busybox    "sh"       1 minutes ago      Up 1 minutes             busybox2
8720575823ec     busybox    "sh"       1 minutes ago      Up 1 minutes             busybox1

下面通過 ping 來證明 busybox1 容器和 busybox2 容器建立了互聯關係。

busybox1 容器輸入以下命令

/ # ping busybox2
PING busybox2 (172.19.0.3): 56 data bytes
64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.072 ms
64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.118 ms

用 ping 來測試連接 busybox2 容器,它會解析成 172.19.0.3

同理在 busybox2 容器執行 ping busybox1,也會成功連接到。

/ # ping busybox1
PING busybox1 (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.064 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.143 ms

這樣,busybox1 容器和 busybox2 容器建立了互聯關係。

如果有多個容器之間需要互相連接,推薦使用 Docker Compose

相關文章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章