docker網絡官網 https://docs.docker.com/network/linux
Docker容器和服務如此強大的緣由之一是您能夠將它們鏈接在一塊兒,或將它們鏈接到非Docker工做負載。Docker容器和服務甚至不須要知道它們已部署在Docker上,也沒必要知道它們的對等對象是否也是Docker工做負載。不管您的Docker主機運行Linux,Windows仍是二者結合,您均可以使用Docker以與平臺無關的方式管理它們。docker
根據網絡的七層模型 以及四層模型來看,最後數據的傳輸都是基於基礎層之上,也就是說兩臺機器的數據傳輸須要經過數據鏈路層進行網絡傳輸,而這一切的功勞得歸屬於網卡。沒有網卡是作不到的。centos
要了解 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
以前咱們提到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,而且是獨立的,咱們能夠進入到容器中進行驗證.
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實現的:
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。
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
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端口訪問到容器。