單host下Docker的默認網(wǎng)絡配置

本文用到的環(huán)境如下:
host: centos7
docker: 通過yum install -y docker安裝,版本號為1.10.3
docker鏡像:
# Version: 0.0.1 FROM ubuntu:latest MAINTAINER paul liu "pollux.liu@msn.com" RUN apt-get update RUN apt-get install -y net-tools RUN apt-get install -y iputils-ping CMD /bin/bash

場景圖:


QQ20160901-7@2x.png

我的host主機接有無線路由器,通過ADSL撥號上網(wǎng),網(wǎng)卡eth0固定IP為192.168.0.200,網(wǎng)關為路由器的IP 192.168.0.1。
在host上安裝docker,并運行容器。

docker0的作用

通過以下命令安裝docker,
yum install -y docker
啟用docker,
systemctl start docker
然后在host主機運行ifconfigip a命令,可以看到除去host原有的網(wǎng)卡eth0和回環(huán)lo外,多了個docker0。

QQ20160901-2@2x.png

docker0 IP為172.17.0.1,所在的網(wǎng)段默認為B類私網(wǎng)地址172.17.0.0/16。可以將docker0看做是host主機的一塊虛擬網(wǎng)卡。這樣host主機就等同于配置了雙網(wǎng)卡,兩塊網(wǎng)卡之間可以通信,但前提是啟用ip_forward。
這是docker0的第一個身份。

運行兩個容器docker1,docker2,然后在host主機上運行brctl show查看,

QQ20160901-8@2x.png

這里可以看出docker0的第二個身份,一個虛擬交換機。每運行一個容器,就會產(chǎn)生一對veth,其中一端連接到docker0上,另一端連接到容器的eth0上。這樣,所有連接到docker0的容器組成了一個局域網(wǎng)。如下圖:

QQ20160901-9@2x.png

在host主機上運行ifconfig,也會發(fā)現(xiàn)多了兩個veth這樣的網(wǎng)絡接口。

在host主機上運行ip addr show veth6d9a691,可以查看到該veth具有mac地址,這也正說明了docker0的虛擬交換機的身份,交換機是通過mac地址通信的,連接到交換機的設備必須具有mac地址。

QQ20160901-10@2x.png

由于docker0自身也具有mac地址,這個與純二層交換機是不同的,并且綁定了IP 172.17.0.1,容器默認把docker0作為了網(wǎng)關。也就是docker0還兼具路由的功能,因此可以把docker0看做是一個三層交換機,可以做二層數(shù)據(jù)包轉(zhuǎn)發(fā),也可以做三層路由轉(zhuǎn)發(fā)。

在容器中運行route -n查看路由如下:

QQ20160901-3@2x.png

在host主機上運行route -n查看路由如下:

QQ20160901-4@2x.png

在host中,訪問本網(wǎng)段192.168.0.0是通過eth0轉(zhuǎn)發(fā)數(shù)據(jù)包的,訪問172.17.0.0網(wǎng)段是通過docker0轉(zhuǎn)發(fā)數(shù)據(jù)包的,而對于其他如公網(wǎng)是通過eth0將數(shù)據(jù)包轉(zhuǎn)發(fā)給網(wǎng)關192.168.0.1,再由該網(wǎng)關進行數(shù)據(jù)包轉(zhuǎn)發(fā)的,比如上網(wǎng)。

容器是如何連接到外部網(wǎng)絡的

在容器中運行ping sohu.comping 192.168.0.200都可以ping通。

默認情況下,不需要再額外做任何配置,在一臺host主機上,通過docker0,各容器之間可以互通,并且可以通過host的eth0連接外網(wǎng)。
通俗的講,通過docker0組成了一個網(wǎng)段為172.17.0.0/16的以太網(wǎng),docker容器發(fā)起請求時,如果是相同網(wǎng)段則經(jīng)由docker0轉(zhuǎn)發(fā)到目標機器,如果是不同網(wǎng)段,則經(jīng)由docker0,轉(zhuǎn)發(fā)到host的另一塊網(wǎng)卡eth0上,由eth0負責下一步的數(shù)據(jù)包轉(zhuǎn)發(fā),比如公網(wǎng)地址。

下面進一步分析一下報文是怎么發(fā)送到外面的。

容器內(nèi)部發(fā)送一條公網(wǎng)請求報文,通過eth0,在veth被接收。此時報文已經(jīng)來到了主機上,通過查詢主機的路由表(route -n),如果發(fā)現(xiàn)報文應該通過主機的eth0,從默認網(wǎng)關發(fā)送出去,那么報文就被從docker0轉(zhuǎn)發(fā)給主機的eth0,但前提是首先啟用ip_forward功能,才能在host主機的docker0和eth0兩個網(wǎng)卡間傳遞數(shù)據(jù)包。

由于目標地址并不屬于host主機所在網(wǎng)段,那么會匹配機器上的 iptables中的nat表POSTROUTING鏈中的規(guī)則。
在host主機運行命令iptables -L -n -t nat --line-numbers,查看nat表,這里只看POSTROUTING鏈:

QQ20160901-6@2x.png

第一行中說明,對于源地址為172.17.0.0/16網(wǎng)段的數(shù)據(jù)包,發(fā)出去之前通過MQSQUERADE偽裝。linux內(nèi)核會修改數(shù)據(jù)包源地址為host主機eth0的地址(也就是192.168.0.200),然后把報文轉(zhuǎn)發(fā)出去。對于外部來說,報文是從主機eth0發(fā)送出去的。

局域網(wǎng)內(nèi)的機器由于都是私有IP,是無法直接訪問互聯(lián)網(wǎng)的(數(shù)據(jù)包可以發(fā)出去,但回不來。)如果要上網(wǎng),除了可以通過硬件路由器,也可以通過軟件路由,在iptables的nat表中的POSTROUTING鏈中添加SNAT規(guī)則。

測試一下,在host主機運行命令iptables -t nat -D POSTROUTING 1將第一條規(guī)則刪掉,那么在容器中就運行命令ping sohu.com就ping不通了。但仍然可以ping通host主機。

在host主機運行命令以下命令恢復:
iptables -t nat -I POSTROUTING -s 172.17.0.0/16 -o eth0 -j SNAT --to-source 192.168.0.200
或者
iptables -t nat -I POSTROUTING -s 172.17.0.0/16 -j MASQUERADE

關于SNAT和MASQUERADE,這篇文章已經(jīng)有過描述,可以參考:Docker前傳之linux iptables

外部網(wǎng)絡如何訪問容器提供的服務

新建一Dockerfile,用以運行nginx容器:
# Version: 0.0.1 FROM paulliu/ubuntu_ip RUN apt-get install -y nginx EXPOSE 80

在host主機運行構(gòu)建命令構(gòu)建鏡像docker build -t paulliu/nginx .
在host主機運行容器啟動命令docker run -d -p 80 --name nginx1 paulliu/nginx nginx -g "daemon off;"
在host主機查看容器的端口映射docker port nginx1 80

QQ20160902-0@2x.png

在host主機運行命令iptables -nat -L -n可以看到在PREROUTING鏈中多了以下DNAT規(guī)則:

QQ20160902-1@2x.png

也就是在容器啟動時通過-p 80將host主機192.168.0.200:32773映射為容器172.17.0.4:80。
注意:docker容器每次啟動時獲取的IP地址未必是一樣的,而且-p 80是在host主機上隨機選擇一個端口號進行映射,每次啟動的端口號也未必是一樣的。但iptables中相關的規(guī)則是自動變更的。

在host主機運行curl localhost:32773或者在其他主機運行curl 192.168.0.200:32773結(jié)果如下:

QQ20160902-2@2x.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容