Docker網絡大揭祕(單機)

  docker網絡官網 https://docs.docker.com/network/linux

  Docker容器和服務如此強大的緣由之一是您能夠將它們鏈接在一塊兒,或將它們鏈接到非Docker工做負載。Docker容器和服務甚至不須要知道它們已部署在Docker上,也沒必要知道它們的對等對象是否也是Docker工做負載。不管您的Docker主機運行Linux,Windows仍是二者結合,您均可以使用Docker以與平臺無關的方式管理它們。docker

計算機網絡模型:

  根據網絡的七層模型 以及四層模型來看,最後數據的傳輸都是基於基礎層之上,也就是說兩臺機器的數據傳輸須要經過數據鏈路層進行網絡傳輸,而這一切的功勞得歸屬於網卡。沒有網卡是作不到的。centos

Linux中網卡:

  要了解 Docker網絡。咱們先來看看基於 Linux 系統的網卡的信息,查看網卡[網絡接口]:tomcat

ip link show
ls /sys/class/net
ip a

  以上三個命令均是查看網卡的信息,咱們來看一下 ip a 所展現出來的網卡信息有哪些?網絡

  咱們能夠看到網卡的基本信息例如當前網卡的狀態(UP/DOWN/UNKOWN等),Mac地址(link/ether),IP地址(inet)。spa

  在Linux中網卡對應的其實就是文件,因此找到對應的網卡文件便可 好比:cat /etc/sysconfig/network-scripts/ifcfg-ens33 。固然,這塊能夠直接修改ifcfg-*文件,可是咱們經過命令添加試試計算機網絡

ip addr add 192.168.1.102/24 dev ens33  添加網卡綁定IP地址

  而後咱們就能夠經過 ip a 來查看:3d

  而後咱們也能夠刪除它:rest

ip addr delete 192.168.1.102/24 dev ens33

  網卡的啓動與關閉:code

重啓網卡 :service network restart / systemctl restart network
啓動/關閉某個網卡 :ifup/ifdown ens33 or ip link set ens33 up/down

Network Namespace 實戰:

  以前咱們提到Docker是基於Linux Kernel的Namespace、CGroups、UnionFileSystem等技術封裝成的一種自定義容器格式,從而提供一套虛擬運行環境。而Namespace用來作隔離的,好比pid[進程]、net[網絡]、mnt[掛載點]等。

  在linux上,網絡的隔離是經過network namespace來管理的,不一樣的network namespace是互相隔離的。

ip netns list:查看當前機器上的network namespace
ip netns add ns1   #添加
ip netns delete ns1 #刪除

  接下去咱們來熟悉一下 Linux 的Namespace的簡單操做,以便以後更加容易的理解Docker的網絡。

1.建立一個network namespace:ip netns add ns1

2.查看該namespace下網卡的狀況:ip netns exec ns1 ip a 。能夠看到剛剛建立出來的 Namespace 的網卡信息是這樣的:

3.啓動ns1上的lo網卡 : ip netns exec ns1 ifup lo   or   ip netns exec ns1 ip link set lo up.再查看其網卡信息

4.再次建立一個network namespace:ip netns add ns2 而後也將其lo網卡啓動:

  那麼如今本臺宿主機上有兩個 network namespace ,分別是 ns1 與 ns2 ,此時此刻這兩個網絡之間是沒法通訊的:

  此時想讓兩個namespace網絡連通起來有什麼辦法呢?在Linux中有一種技術 veth pair :Virtual Ethernet Pair,是一個成對的端口,能夠實現上述功能。

1.建立一對link,也就是接下來要經過veth pair鏈接的link :ip link add veth-ns1 type veth peer name veth-ns2 。這個命令就是添加一對veth pair,即 veth-ns1 與 veth-ns2 是一對。

2.查看 link 狀況 :ip link:

3.將veth-ns1加入ns1中,將veth-ns2加入ns2中:

ip link set veth-ns1 netns ns1
ip link set veth-ns2 netns ns2

4.查看宿主機和ns1,ns2的link狀況,能夠發現這個pair對已經分配到了指定的 namespace了:

5.此時veth-ns1和veth-ns2尚未ip地址,顯然通訊還缺乏點條件,爲其添加IP:

ip netns exec ns1 ip addr add 192.168.1.11/24 dev veth-ns1
ip netns exec ns2 ip addr add 192.168.1.12/24 dev veth-ns2

6.啓動veth-ns1和veth-ns2:

ip netns exec ns1 ip link set veth-ns1 up
ip netns exec ns2 ip link set veth-ns2 up

7.而後查看這兩個網卡的信息:

8.此時兩個network namespace互相ping一下,發現是能夠ping通的:


  這就是咱們對 network namespace 的基本認識。

Container 的 network namespace:

  按照上面的描述,實際上每一個container,都會有本身的network namespace,而且是獨立的,咱們能夠進入到容器中進行驗證.

1.不妨建立兩個container看看?

docker run -d --name tomcat01 -p 8081:8080 tomcat
docker run -d --name tomcat02 -p 8082:8080 tomcat

2.進入到兩個容器中,而且查看ip.互相ping一下是能夠ping通的.由於他們在一個網段。

  值得咱們思考的是,此時tomcat01和tomcat02屬於兩個network namespace,是如何可以ping通的?有些小夥伴可能會想,不就跟上面的namespace實戰同樣嗎?注意這裏並無veth-pair技術。

深刻分析container網絡-Bridge:

1.docker0默認bridge,查看centos的網絡:ip a,能夠發現,重點看跟docker有關係的3個網卡:

2.查看容器tomcat01的網絡:docker exec -it tomcat01 ip a,能夠發現:


3.在centos中ping一下tomcat01的網絡,發現能夠ping通。

  既然能夠ping通,並且centos和tomcat1又屬於不一樣的network namespace,是怎麼鏈接的?很顯然,跟以前的實戰是同樣的,畫個圖:

  也就是說,在tomcat01中有一個 eth0 和 centos 的 docker0 中有一個vetha4 是成對的,相似於以前實戰中的veth-ns1和veth-ns2,不妨再經過一個命令確認下:brctl。安裝一下:yum install bridge-utils.咱們能夠看到docker0下有兩個接口,即就是tomcat01-02裏面的網卡接口。

  那爲何tomcat01和tomcat02能ping通呢?很少說,直接上圖:

  這種網絡鏈接方法咱們稱之爲Bridge,其實也能夠經過命令查看docker中的網絡模式:docker network ls 。bridge也是docker中默認的網絡模式:

  能夠看到有三種類型的網絡模式: bridge , host ,none。還有一種多機通信的 overlay 。

  不妨檢查一下bridge:docker network inspect bridge :

  在tomcat01容器中是能夠訪問互聯網的,順便把這張圖畫一下咯,NAT是經過iptables實現的:

建立本身的network( 類型:bridge ):

1.建立一個network,類型爲bridge

docker network create tomcat-net
or
docker network create --subnet=172.19.0.0/24 tomcat-net

2.查看已有的network:docker network ls

3.查看tomcat-net詳情信息:docker network inspect tomcat-net

4.建立tomcat的容器,而且指定使用tomcat-net : docker run -d --name custom-net-tomcat --network tomcat-net tomcat

5.查看custom-net-tomcat的網絡信息 :  docker exec -it custom-net-tomcat ip a

6.此時在custom-net-tomcat容器中ping一下tomcat01的ip會如何?發現沒法ping通

  而此時此刻整個 Network Namespace 是這樣的:

7.此時若是tomcat01容器可以鏈接到tomcat-net上應該就能夠:執行 docker network connect tomcat-net tomcat01

8.查看tomcat-net詳情信息:docker network inspect tomcat-net

  再看看 tomcat01的網卡狀態:

  此時進入到tomcat01或者custom-net-tomcat中,不只能夠經過ip地址ping通,並且能夠經過名字ping到,這時候由於都鏈接到了用戶自定義的tomcat-net bridge上 (可是ping tomcat02是不通的)

  可是若是實在默認的 docker0 的網絡中 ,經過 ping +容器名是不會通的,想要通就要在建立容器的時候加上參數  --link  +容器名,且該命令是單向的。不推薦在生產上這麼作,推薦用自定義network。

Container網絡Host:

1.建立一個tomcat容器,而且指定網絡爲host :docker run -d --name my-tomcat-host --network host tomcat

2.查看ip地址 :docker exec -it my-tomcat-host ip a  能夠發現和centos是同樣的:

3.檢查host網絡:docker network inspect host

 

Container網絡 None :

1.建立一個tomcat容器,而且指定網絡爲none: docker run -d --name my-tomcat-none --network none tomcat

2.查看ip地址 :docker exec -it my-tomcat-none ip a .會發現他是與世隔絕的一種模式

端口映射:

  端口映射也是解決docker 網絡通信的手段之一。好比咱們在建立容器的時候指定映射端口:

docker run -d --name port-tomcat -p 8090:8080 tomcat

  這樣子就能夠經過宿主機的IP加8090端口訪問到容器。

相關文章
相關標籤/搜索