Docker網路介紹
title: Docker網路
tags: Docker
大量的網際網路應用服務包括多個服務元件,這往往需要多個容器之間通過網路通訊進行相互配合。
一、網路基礎
在瞭解Docker的網路之前,必須先認識Docker所依賴的幾個linux技術,這對理解docker的網路有幫助。
Docker的網路實現其實就是利用了 Linux上的網路名稱空間和虛擬網路裝置(特別是veth pair)。熟悉這兩部分的基本概念,可以有助於理解 Docker網路的實現過程。
1.名稱空間
Linux Namespaces機制提供一種資源隔離方案。PID,IPC,Network等系統資源不再是全域性性的,而是屬於特定的Namespace。每個Namespace裡面的資源對其他Namespace都不可見。
一個Network Namespace提供了一份獨立的網路環境,包括網絡卡、路由、Iptable規則等都與其他的Network Namespace隔離。一個Docker容器“通常”會分配一個獨立的Network Namespace。這樣每個docker容器就好像擁有了一套獨立的網路環境,甚至以為自己霸佔了全部的主機,也許這也是使人們經常認為容器就是虛機的原因之一吧。
現在我們就來演示一下:
1.1我們先執行兩個busybox
容器:
docker run -d --name test1 busybox /bin/sh -c "while true; do sleep 3600; done"
docker run -d --name test2 busybox /bin/sh -c "while true; do sleep 3600; done"
1.2 檢視2個容器網路
docker exec -it test1 ip a
docker exec -it test2 ip a
我們可以看到test1和test2是兩個不同的網路環境。
1.3新增namespace
ip netns add test1
ip netns add test2
1.4檢視本機的namespace
ip netns exec test1 ip a
ip netns exec test2 ip a
namespace預設是DOWN的狀態
2.Veth裝置對
Veth裝置對可以在不同的網路名稱空間之間通訊,用他們可以連線兩個網路名稱空間。一對veth裝置就像網線的兩頭一樣。
1.把namespace變成up狀態
ip netns exec test1 ip link set dev lo up
狀態變成了 unknown,為什麼是unknown呢,因為當前的test1沒有被連通。
2.建立並檢視link
ip link add veth-test1 type veth peer name veth-test2
檢視linkip link
3.新增veth-test1 到namespace
ip link set veth-test1 netns test1
4.新增並檢視veth-test2
ip link set veth-test2 netns test2
ip netns exec test2 ip link
3.網橋
簡單來說,橋接就是把一臺機器上的若干個網路介面“連線”起來。其結果是,其中一個網口收到的報文會被複制給其他網口併發送出去。以使得網口之間的報文能夠互相轉發。類似交換機。
linux核心支援網口的橋接與交換機有一點點不同不同,交換機只是一個二層裝置,對於接收到的報文,要麼轉發、要麼丟棄。而執行著linux核心的機器本身就是一臺主機,有可能就是網路報文的目的地。其收到的報文除了轉發和丟棄,還可能被送到網路協議棧的上層(網路層),從而被自己消化。
在docker啟動時,會在主機上建立一個docker0網橋。通過docker0在同一個主機上的容器之間都可以通訊,外部的訊息也可以經過docker0進入容器。
1.為test1和test2分配IP地址
ip netns exec test1 ip addr add 192.168.1.1/24 dev veth-test1
ip netns exec test2 ip addr add 192.168.1.1/24 dev veth-test2
2.link並啟動
ip netns exec test1 ip link set dev veth-test1 up
ip netns exec test2 ip link set dev veth-test2 up
3.兩個namespace可以ping通了
ip netns exec test1 ping 192.168.1.2
二、網路建立過程
Docker建立一個容器的時候,會具體執行如下操作:
- 建立一對虛擬介面,分別放到本地主機和新容器的名稱空間中。
- 本地主機一端的虛擬介面連線到預設的 docker0網橋或指定網橋上,並具有一個以veth開頭的唯一名字,如veth1234。
- 容器一端的虛擬介面將放到新建立的容器中,並修改名字作為eth0。這個介面只在容器的名稱空間可見。
- 從網橋可用地址段中獲取一個空閒地址分配給容器的eth0(例如172.17.0.2/16),並配置預設路由閘道器為 docker網絡卡的內部介面 docker的IP地址(例如172.17.42./16)。
完成這些之後,容器就可以使用它所能看到的eth0虛擬網絡卡來連線其他容器和訪問外部網路。
三、埠對映
在啟動容器的時候,如果不指定對應引數,在容器外部是無法通過網路來訪問容器內的網路應用和服務的。
當容器中執行一些網路應用,要讓外部訪問這些應用時,可以通過-P或-p引數來指定埠對映。當使用-P標記時, Docker會隨機對映一個
我們先演示下沒有對映埠的情況:
1.啟動一個nginx容器
docker run --name web -d nginx
2.檢視橋接網路狀態
docker network inspect bridge
獲得IP:172.17.0.4
- 在容器內訪問
curl http://172.17.0.4
- 在容器外訪問
curl http://172.17.0.4
訪問被拒絕
現在我們新增埠演示:
1.先停止並刪除容器
docker stop web
docker rm web
2.重新建立容器,並指定埠對映
docker run --name web -d -p 80:80 nginx
3.再來測試外部訪問,為了能更好的感受到,我們使用瀏覽器訪問
四、預設網路
安裝Docker時,它會自動建立三個網路:bridge NetWork
(橋接網路)、Host NetWork
(主機網路)、None NetWork
(無網路)
這三個網路都是用於單機。
這三個網路內置於Docker中。執行容器時,可以使用 --network
或者-- net
標誌指定容器應連線到的網路。
bridge網路代表docker0所有Docker安裝中存在的網路。除非你使用該docker run --network=<NETWORK>
選項指定,否則Docker守護程式預設將容器連線到此網路。。
我們可以使用docker network inspect <net>
來檢視某個網路資訊。
例:
docker network inspect bridge
五、Docker網路模式
Docker有以下4種網路模式:
- Bridge模式:使用–net=bridge指定,預設設定;
- Host模式:使用–net=host指定;
- Container模式:使用–net=container:NAME_or_ID指定;
- None模式:使用–net=none指定。
你可以使用以docker network ls
命令列出這些網路:
1.Bridge
Bridge是Docker網路預設模式,相當於Vmware中的Nat模式,容器使用獨立network Namespace,並連線到docker0虛擬網絡卡(預設模式)。通過docker0網橋以及Iptables nat表配置與宿主機通訊;bridge模式是Docker預設的網路設定,此模式會為每一個容器分配Network Namespace、設定IP等,並將一個主機上的Docker容器連線到一個虛擬網橋上。
在Bridge模式下:
- 主機上面會有一個docker0的網橋;
- 每個容器都與docker0連通,所以同主機上的容器之間也連通;
- 每個主機上容器的地址都是從172.17.0.2開始往後分。
安裝brctl
yum -y install brige-utils
檢視本機的veth
brctl show
2.Host
相當於Vmware中的橋接模式,與宿主機在同一個網路中,但沒有獨立IP地址。如果啟動容器的時候使用host模式,那麼這個容器將不會獲得一個獨立的Network Namespace,而是和宿主機共用一個Network Namespace。容器將不會虛擬出自己的網絡卡,配置自己的IP等,而是使用宿主機的IP和埠。
3.None
在這種模式下,Docker容器擁有自己的Network Namespace,但是,並不為Docker容器進行任何網路配置。也就是說,這個Docker容器沒有網絡卡、IP、路由等資訊。需要我們自己為Docker容器新增網絡卡、配置IP等。以下情況下是有用的:容器並不需要網路。
4.Container
這個模式指定新建立的容器和已經存在的一個容器共享一個Network Namespace,而不是和宿主機共享。新建立的容器不會建立自己的網絡卡,配置自己的IP,而是和一個指定的容器共享IP、埠範圍等。同樣,兩個容器除了網路方面,其他的如檔案系統、程序列表等還是隔離的。