Docker網絡實現原理:linux
Docker 中的網絡接口默認都是虛擬的接口。虛擬接口的優點之一是轉發效率較高。 Linux 經過在內核中進 行數據複製來實現虛擬接口之間的數據轉發,發送接口的發送緩存中的數據包被直接複製到接收接口的接收緩存中。對於本地系統和容器內系統看來就像是一個正常的以太網卡,只是它不須要真正同外部網絡設備通訊,速度要快不少;Docker 容器網絡利用此技術,它在本地主機和容器內分別建立一個虛擬接口,並讓它們彼此連通 (這樣的一對接口叫作 veth pair )docker
Docker 建立一個容器的時候,會執行以下操做:緩存
建立一對虛擬接口,分別放到本地主機和新容器中; 服務器
本地主機一端橋接到默認的 docker0 或指定網橋上,並具備一個惟一的名字,如 vethf9; 網絡
容器一端放到新容器中,並修更名字做爲 eth0,這個接口只在容器的名字空間可見; ide
從網橋可用地址段中獲取一個空閒地址分配給容器的 eth0,並配置默認路由到橋接網卡 vethf9。 oop
完成這些以後,容器就可使用 eth0 虛擬網卡來鏈接其餘容器和其餘網絡url
網絡模式須要開啓linux系統轉發功能,查看linux系統中是否開啓轉發功能:spa
#sysctl net.ipv4.ip_forwardcode
net.ipv4.ip_forward = 1
設置:sysctl -w net.ipv4.ip_forward=1
幾種網絡模式:
Nat --net=bridge (默認的網橋),Docker經過宿主機的網橋(docker0)來連通內部和宿主機的網絡,實現了容器與宿主機和外界之間的網絡通訊
Bridge橋接模式的實現步驟主要以下:
(1)Docker Daemon利用veth pair技術,在宿主機上建立兩個虛擬網絡接口設備,假設爲veth0和veth1。而veth pair技術的特性能夠保證不管哪個veth接收到網絡報文,都會將報文傳輸給另外一方。
(2)Docker Daemon將veth0附加到Docker Daemon建立的docker0網橋上。保證宿主機的網絡報文能夠發往veth0。
(3)Docker Daemon將veth1添加到Docker Container所屬的namespace下,並被更名爲eth0。如此一來,保證宿主機的網絡報文若發往veth0,則當即會被eth0接收,實現宿主機到Docker Container網絡的聯通性;同時,也保證Docker Container單獨使用eth0,實現容器網絡環境的隔離性。
同時Docker採用NAT(Network Address Translation,網絡地址轉換)的方式(可自行查詢實現原理),讓宿主機之外的世界能夠主動將網絡報文發送至容器內部。
經過Bridger網橋模式實現:
(1)容器擁有獨立、隔離的網絡棧
(2)容器和宿主機之外的世界經過NAT創建通訊
Host --net=host (告訴docker不要將容器網絡放在隔離的名字容器中,即不要容器化容器內的網絡,該模式下的Docker Container和host宿主機共享同一個網絡namespace,即container和宿主機同樣,使用宿主機的eth0)
Docker Container的host網絡模式在實現過程當中,因爲不須要額外的網橋以及虛擬網卡,故不會涉及docker0以及veth pair。父進程在建立子進程時,若是不使用CLONE_NEWNET這個參數標誌,那麼建立出的子進程會與父 進程共享同一個網絡namespace。Docker就是採用了這個簡單的原理,在建立進程啓動容器的過程當中,沒有傳入CLONE_NEWNET參數標 志,實現Docker Container與宿主機共享同一個網絡環境,即實現host網絡模式。
Docker Container的網絡模式中,host模式是bridge橋接模式很好的補充。採用host模式的Docker Container,能夠直接使用宿主機的IP地址與外界進行通訊,若宿主機的eth0是一個公有IP,那麼容器也擁有這個公有IP。同時容器內服務的端口也可使用宿主機的端口,無需額外進行NAT轉換。固然,有這樣的方便,確定會損失部分其餘的特性,最明顯的是Docker Container網絡環境隔離性的弱化,即容器再也不擁有隔離、獨立的網絡棧。另外,使用host模式的Docker Container雖然可讓容器內部的服務和傳統狀況無差異、無改造的使用,可是因爲網絡隔離性的弱化,該容器會與宿主機共享競爭網絡棧的使用;另外,容器內部將再也不擁有全部的端口資源,緣由是部分端口資源已經被宿主機自己的服務佔用,還有部分端口已經用以bridge網絡模式容器的端口映射。
Other container --net=container:NAME_or_ID (讓docker將新建容器的進程放到一個已存在容器的網絡棧中,新容器進程有本身的文件系統、進程列表和資源限制,但會和已存在的容器共享IP地址和端口等網絡資源,二者進程能夠直接經過lo 環回接口通訊)
上圖右側的Docker Container即採用了other container網絡模式,它能使用的網絡環境即爲左側Docker Container brdige橋接模式下的網絡
Docker Container的other container網絡模式在實現過程當中,不涉及網橋,一樣也不須要建立虛擬網卡veth pair。
完成other container網絡模式的建立只須要兩個步驟:
(1) 查找other container(即須要被共享網絡環境的容器)的網絡namespace;
(2) 將新建立的Docker Container(也是須要共享其餘網絡的容器)的namespace,使用other container的namespace
在這種模式下的Docker Container能夠經過localhost來訪問namespace下的其餘容器,傳輸效率較高。雖然多個容器共享網絡環境,可是多個容器造成的總體依然與宿主機以及其餘容器造成網絡隔離。另外,這種模式還節約了必定數量的網絡資源。可是須要注意的是,它並無改善容器與宿主機之外世界通訊的狀況。
None --net=none (讓Docker將新容器放到隔離的網絡棧中,但不進行網絡配置,以後用戶能夠本身進行配置,容器內部只能使用loopback網絡設備,不會再有其餘的網絡資源)
網絡相關的命令:
-b BRIDGE or --bridge=BRIDGE --指定容器掛載的網橋
--bip=CIDR --定製 docker0 的掩碼
-H SOCKET... or --host=SOCKET... --Docker 服務端接收命令的通道
--icc=true|false --是否支持容器之間進行通訊
--ip-forward=true|false --容器之間的通訊
--iptables=true|false --禁止 Docker 添加 iptables 規則
--mtu=BYTES --容器網絡中的 MTU
下面2個命令選項既能夠在啓動服務時指定,也能夠 Docker 容器啓動( docker run )時候指定。在 Docker 服務啓動的時候指定則會成爲默認值,後面執行 docker run 時能夠覆蓋設置的默認值:
--dns=IP_ADDRESS... --使用指定的DNS服務器
--dns-search=DOMAIN... --指定DNS搜索域
下面這些參數只有在docker run執行時使用,主要針對容器特性:
-h HOSTNAME or --hostname=HOSTNAME --配置容器主機名
--link=CONTAINER_NAME:ALIAS --添加到另外一個容器的鏈接
--net=bridge|none|container:NAME_or_ID|host --配置容器的橋接模式
-p SPEC or --publish=SPEC --映射容器端口到宿主主機
-P or --publish-all=true|false --映射容器全部端口到宿主主機
上述網絡模式理論主要來自連接:
http://www.infoq.com/cn/articles/docker-source-code-analysis-part7