Docker的應用運行在容器中,其相互之間或與外部之間是如何通信的,涉及到哪些知識點,本文對相關內容進行整理。因網絡這塊牽涉的面較多,因此只從日常使用或理解的角度出發,過於專業的就不深入探討了。
1. Docker默認的網絡拓撲
在Docker筆記(二):Docker管理的對象中,介紹了Docker通過一些驅動程序來實現容器之間或容器與外部的互聯,包括bridge(默認的虛擬網橋形式),host(與主機共享網絡棧),overlay(跨Docker Daemon容器間的互聯),macvlan(為容器分配mac地址),none(禁用所有網絡)等。
默認情況下,Docker啟動時會創建一個虛擬網橋 docker0,可以理解為一個軟件交換機。當創建一個 Docker 容器的時候,會創建一對 veth pair 接口(當數據包發送到一個接口時,另外一個接口也可以收到相同的數據包)。這對接口一端在容器內,即 eth0 ;另一端在宿主機本地並被掛載到 docker0 網橋,名稱以veth 開頭,如 veth340c305,docker0會在掛載到它上面的網口之間進行轉發,從而實現主機與容器之間及容器與容器之間的相互通信。Docker默認的網絡拓撲圖如下:
我們可以在宿主機上通過ifconfig
查看相關的網絡接口,
~$ ifconfig |
通過brctl show
可查看網絡接口的掛載情況,
~$ brctl show |
由上可看出網絡接口veth340c305,veth6c803b7都掛在虛擬網橋docker0上。
2. 容器與外部的互聯
我們前面的許多容器啟動命令都有添加類似 -p 8080:8080 的參數,以指定將宿主機端口映射到容器端口,從而通過訪問 宿主機IP:宿主機端口
的地址來訪問對應端口的容器服務。
端口映射的完整格式為 宿主機IP:宿主機端口:容器端口
,其中前兩個是可以兩者都取,或只取其一
宿主機IP:宿主機端口:容器端口
:將指定宿主機IP的一個指定端口映射到容器端口,如192.168.40.205:8090:8080
宿主機IP::容器端口
:將指定宿主機IP的一個隨機端口映射到容器端口上,如果宿主機有多個IP,則可以通過這種格式指定綁定其中一個宿主機IP,隨機端口范圍為49000~49900宿主機端口:容器端口
:將宿主機所有網絡接口IP的指定端口映射到容器端口上,8090:8080
等效於0.0.0.0:8090:8080
(0.0.0.0
即表示所有網絡接口地址)
可以使用 docker port 容器ID或名稱 容器端口
或docker ps
命令來查看端口映射情況,如
~$ docker port test-dev 8080 |
在容器啟動時,可以多次使用 -p 來指定映射多個端口。
如果不指定具體的宿主機端口,則可以使用 -P(大寫)來分配一個宿主機的隨機端口(范圍為49000~49900), 如docker run -d -P --name test-dev test:dev
,然后通過docker port 容器ID或名稱 容器端口
或docker ps
命令來查看具體映射到了哪個端口。
3. 容器之間的互聯
同一個Docker Daemon下的容器,彼此之間是可以通過容器IP互相訪問的(如何查看容器IP?用docker inspect 容器ID或名稱
命令),如果要實現兩個容器之間可以通過容器名直接訪問,則可以通過自建一個docker網絡。
|
由上可見通過自定義網橋連接的容器可以通過容器名稱互相訪問。如果需要多個容器之間互聯,則可以使用Docker Compose。
4. 配置容器的DNS
如果要自定義所有容器的DNS,則可以在 /etc/docker/daemon.json 中增加
{ |
也可以在啟動容器時通過參數指定單個容器的DNS配置,--dns=IP_ADDRESS
,這會將指定DNS的地址添加到容器的 /etc/resolv.conf 文件中,讓容器用這個DNS服務器來解析所有不在 /etc/hosts 中的主機名。
5. Docker網絡的底層實現
容器的網絡訪問控制,主要是通過Linux上的iptables防火牆來實現與管理的。
1. 容器訪問外部網絡
容器訪問外部網絡,需要通過本地系統的轉發,可以通過如下命令查看轉發是否打開
|
容器所有到外部網絡的訪問,源地址都會被 NAT 成本地系統的 IP 地址。這是使用 iptables 的源地址偽裝操作實現的,
~# iptables -t nat -nL |
上述規則將所有源地址在 172.17.0.0/16 的網段(容器IP所在網段),目標地址為任意網段(包括外部網絡)的流量動態偽裝為從系統網卡發出。MASQUERADE 跟傳統 SNAT 的好處是它能動態從網卡獲取地址。
2. 外部訪問容器
通過 -p 或 -P 指定端口映射,允許外部訪問容器端口,實質也是在本地的 iptable 的 nat 表中添加相應的規則,如
~# iptables -t nat -nL |
這里的規則映射了 0.0.0.0 ,意味着將接受主機來自所有網絡接口的流量。
3. 容器之間的訪問
容器之間能互相訪問,需要滿足兩個條件:1)容器的網絡拓撲是否已經互聯,默認情況下容器都連接到docker0網橋上,默認是互聯的。2)本地系統的防火牆iptables是否允許通過。當容器啟動時通過–link互聯時,也是在iptables中創建對應規則來實現。
6. 總結
本文整理了Docker網絡相關知識,對容器之間及容器與外部之間的通信機制應該有了一定的了解。除了默認的網絡實現,Docker還提供了網絡的配置及自定義網絡,出於篇幅,本文介紹到這,后續再補充。
相關閱讀
Docker筆記(二):Docker管理的對象
Docker筆記(三):Docker安裝與配置
Docker筆記(四):Docker鏡像管理
Docker筆記(五):整一個自己的鏡像
Docker筆記(六):容器管理
Docker筆記(七):常用服務安裝——Nginx、MySql、Redis
我的微信公眾號:jboost-ksxy (一個不只有技術干貨的公眾號,歡迎關注,及時獲取更新內容)