Docker學習<四>
Docker網絡
Docker安裝時會自動在host上創建bridge、host、none這三個網絡,可以用docker network ls命令來查看
none網絡
none網絡就是什麽網絡都沒有,掛在這個網絡下的容器除了lo,沒有其他任何網卡,創建容器時可以通過--network=none來指定使用none網絡。對一些安全性要求高並且不需要聯網的應用可以使用none網絡。除此之外,我們要實現容器的集中管控也可以使用none網絡,比如要使所創建的網絡受控於SDN網絡,則可以先用none網絡來啟動容器,然後再將該網絡連接到OVS的網橋上,使其受控於SDN的控制器
host網絡
連接到host網絡的容器共享Docker host的網絡棧,容器的網卡配置與host完全一致,可以通過--network=host來指定使用host網絡。直接使用Docker host的網絡最大的好處就是性能,如果容器對網絡傳輸效率有較高要求,則可用host網絡,但它的靈活性不高,比如要考慮端口沖突的問題,Docker host上已經使用的端口則不能再使用。它的另一個用途是讓容器可以直接配置host網絡,比如某些跨主機的網絡
bridge網絡
Docker安裝時會創建一個命名為docker0的linux bridge,如果不指定--network,創建的容器默認都會掛到docker0上,可以使用docker network inspect bridge查看網絡的配置信息。容器創建時,docker會自動從172.17.0.0/16中分配一個IP,這裏16位掩碼保證有足夠多的IP可以供容器使用
user-defined網絡
Docker提供三種user-defined網絡驅動:bridge、overlay和macvlan。其中overlay和macvlan用於創建跨主機的網絡
可以通過bridge驅動創建類似前面默認的bridge網絡,這裏的172.18.0.0/16是Docker自動分配的IP網段
也可以自己指定IP網段,只需在創建網段時指定--subnet和--gateway參數,下面來創建一個新的bridge網絡mynet1,網段為172.22.16.0/24,網關為172.22.16.1
用創建的mynet1網絡來啟動一個容器並查看它的IP地址,可以看到容器已經被分配到IP為172.22.16.2
Docker創建容器時都是自動從subnet中分配IP,我們也可以給容器指定一個靜態IP,用--ip參數來實現
需要註意的是,只有使用--subnet創建的網絡才能指定靜態IP,前面創建mynet網絡時並沒有使用--subnet,如果使用mynet網絡來指定靜態IP,則會出錯
如果我們不再需要自定義創建的網絡時,也可以刪除它們
接下來來驗證各個主機之間的連通性,由於上面創建的主機比較多,而且每個各個主機可能在不同的網絡類型下,為了更加直觀的看出主機間的網絡情況,這裏繪制了一個簡單的網絡拓撲結構圖
host3和host4兩個容器都掛在mynet1上,是可以相互通信的,下面來驗證它們之間的連通性。由結果可以看出同一網絡中的容器、網關之間都能相互通信
mynet1與docker0屬於不同的網橋,它們之間應該不能直接通信。下面來驗證host3與host5之間的連通性。結果表明它們的確不能相互通信
不同網絡如果加上路由是可以通信的。用ip r來查看host上的路由表
由路由表可以看出172.17.0.0/16和172.22.16.0/24兩個網絡的路由都定義好了
查看ip forwarding
ip forwarding也已經啟動
雖然該有的條件已經滿足,但不同網絡還是無法通信,接下來查看iptables
sudo iptables-save
原因就在這裏:iptables DROP掉了網橋docker0與br-305c071332d6之間的雙向流量。從規則的命名DOCKER-ISOLATION可知docker在設計上就是要隔離不同的network
要實現host3與host5之間的通信,可以用一下方法:為host5容器添加一塊mynet1的網卡,通過docker network connect命令實現
host5中查看網絡配置
可以看出容器中增加了一個網卡eth1,分配了mynet1的IP 172.22.16.3,現在host3與host5之間可以相互通信了,下面來驗證它們的連通性
容器間的三種通信方法
IP通信
兩個容器要能夠通信,必須要有屬於同一個網絡的網卡,滿足這個條件後,就可以通過IP交互了。具體實現方法是創建容器時通過--network指定相應的網絡,或通過docker network connect將現有的容器加到指定的網絡
Docker DNS Server
IP通信的靈活性不高,因為部署應用前可能無法確定IP,部署後再指定要訪問的IP會比較麻煩,解決這一問題的方法是通過docker自帶的DNS服務。從Docker1.10版本開始,docker daemon實現了一個內嵌的DNS server,使容器可以直接通過“容器名”通信,方法很簡單,只需在啟動容器時用--name為容器命名就可以了
使用docker DNS有個限制:只能在user-defined網絡中使用,默認的bridge網絡是無法使用DNS的,下面看一個例子
joined容器
joined容器可以使兩個或多個容器共享一個網絡棧,共享網卡和配置信息,joined容器間可以通過127.0.0.1直接通信
joined容器適合以下場景
1. 不同容器中程序希望通過loopback高效快速地通信,比如web server與app server
2. 希望監控其他容器的網絡流量,比如運行在獨立容器中的網絡監控程序
外部網絡訪問容器
docker可將容器對外提供服務的端口映射到host的某個端口,外網通過該端口訪問容器。容器啟動時通過-p參數映射端口
容器啟動後可以通過docker ps或docker port查看host映射的端口。上面例子中web2容器的80端口被映射到host的32768上,這樣就可以在host上通過<host ip>:<32768>訪問到容器的web服務
除了映射動態端口,也可在-p中指定映射到host某個特定端口。例如可將80端口映射到host的8080端口
每個映射的端口,host都會啟動一個docker-proxy進程來處理訪問容器的流量
以0.0.0.0:32768—>80/tcp為例分析整個過程
1. docker-proxy監聽host的32768端口
2. 當curl訪問127.0.0.1:32768時,docker-proxy轉發給容器172.17.0.5:80
3. httpd容器響應請求並返回結果
Docker學習<四>