docker在1.9版本以後,引入了一套docker network子命令來管理docker網絡。這容許用戶能夠根據他們應用的拓撲結構建立虛擬網絡並將容器接入其所對應的網絡。docker
具體來講,docker網絡是經過一個叫libnetwork的東西來進行管理的,用docker network命令對docker網絡進行操做其實是與libnetwork Api進行交互。segmentfault
libnetwork內置有五種網絡驅動,分別是:bridge驅動、host驅動、overlay驅動、remote驅動、null驅動。這些網絡驅動爲docker提供了多種網絡模式。下面咱們簡單說說各驅動的做用:網絡
bridge驅動即爲一般說的橋接模式,此驅動爲Docker的默認驅動,該驅動的做用爲將Docker容器鏈接到docker默認建立的docker0網橋上面,若是未指定--network選項,建立的容器將默認指向docker0,該驅動即對應docker的bridge網絡模式,經過NAT地址轉換使容器和外界進行通訊。tcp
可以使用以下命令查看docker0網橋,該網橋會在docker安裝後自動配置:性能
ip addr
咱們能夠看到默認的docker0網橋ip爲172.17.0.1/16,在某些狀況下假如咱們宿主機網段與docker0網段相同,咱們用bridge模式默認的docker0網橋會與宿主機產生網段衝突問題,這時候只須要更改docker0默認的網段或者使用docker容器的--network選項選擇用戶自定義的網橋便可解決。spa
該驅動將docker容器與宿主機網絡處於同一個network namespace下,docker容器將使用宿主機的網卡、ip和端口信息,故容器與外界不進行NAT地址轉換,增長了網絡性能,可是缺點是宿主機上已使用的端口docker容器不能再使用,該驅動對應docker的host網絡模式。插件
此驅動採用IETE標準的VXLAN方式,具體VXLAN實現方式這裏暫不說明,該驅動主要用於建立容器的跨主機網絡,對應docker的user-defined網絡模式。code
這個驅動用於用戶向libnetwork提供自定義的網絡插件,並無實現任何網絡功能。圖片
null驅動即爲docker容器的none網絡模式,該模式併爲docker容器提供任何網絡配置,只有docker容器自身的lo網卡,該模式通常用於一些特定的狀況。ip
咱們經常使用的docker網絡模式通常都是bridge模式,下面咱們來分析docker是如何實現橋接網絡的。
首先咱們能夠經過以下命令查看docker0網關:
route -n
從如上命令能夠看出全部指向ip爲172.17.0.0/16的數據包都從docker0網卡轉發。
而後咱們用docker run命令啓動一個容器名爲demo,進入容器demo,一樣用ip addr或ifconfig命令查看網卡,咱們能夠看到以下兩個網卡:
lo網卡和eth0網卡。lo網卡即爲容器自身的迴環網卡,eth0網卡ip爲172.17.0.3/16,和宿主機網卡docker0在同一網段,這時咱們用route -n命令查看demo容器的網關以下:
能夠看出demo的eth0網卡與宿主機的docker0網卡是相互連通的。
這時退出demo容器再來用ip addr查看宿主機的網絡設備,會發現有一塊以「veth」開頭的網卡,如veth5653371,咱們能夠猜想veth5653371與demo容器內的eth0網卡是一對veth設備(veth pair老是成對出現),veth設備的做用爲用來鏈接兩個不一樣的network namespace,故docker0不是單純的網卡而是網橋了,這就是docker的bridge網絡模式的實現方式,經過鏈接docker0網橋來實現宿主機和容器的網絡互通。
咱們知道了docker的bridge網絡模式的網絡互通方式,那麼docker是如何實現宿主機和容器的端口映射的呢?這一切都靠配置iptables規則來實現,具體表現以下:
Docker安裝完成後,將默認在宿主機系統上增長一些iptables規則,用iptables-save命令查看如下規則:
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
上面這條規則關係着Docker容器和外界的通訊,含義是:將源地址爲172.17.0.0/16的數據包(即Docker容器發出的數據),當不是從docker0網卡發出時作SNAT。這樣docker容器訪問外部的流量會認爲是宿主機發出的。
同理,docker容器和宿主機的端口映射也是經過iptalbes映射來實現的,假設咱們啓動一個容器將其端口8080映射到宿主機端口8080上,咱們能夠看到以下規則:
-A POSTROUTING -s 172.17.0.3/16 -d 172.17.0.3/16 -p tcp -m tcp --dport 8080 -j MASQUERADE -A DOCKER -d 172.17.0.3/16 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8080 -j ACCEPT
該規則將訪問宿主機8080端口的流量轉發到172.17.0.3/16(即demo容器的etho網卡)上,因此docker是經過配置iptalbes規則來實現端口映射的。
到目前爲止,咱們所講的docker網絡環境僅僅是對單機而言的,要實現不一樣宿主機的網絡互一般常有多種方式,我這裏選用的是flannel來實現不一樣宿主機容器的網絡互通,這也是kubernetes實現網絡互通的方式,要想知道flannel是如何實現網絡互通的,請查看個人下一篇博文:flannel解讀