當 Docker 啓動時,會自動在主機上建立一個 docker0 虛擬網橋,其實是 Linux 的一個 bridge,能夠理解爲一個軟件交換機。它會在掛載到它的網口之間進行轉發。
同時,Docker 隨機分配一個本地未佔用的私有網段(在 RFC1918 中定義)中的一個地址給 docker0 接口。好比典型的 172.17.42.1 ,掩碼爲 255.255.0.0 。此後啓動的容器內的網口也會自動分配一個同一網段( 172.17.0.0/16 )的地址。
當建立一個 Docker 容器的時候,同時會建立了一對 veth pair 接口(當數據包發送到一個接口時,另一個接口也能夠收到相同的數據包)。這對接口一端在容器內,即 eth0 ;另外一端在本地並被掛載到docker0 網橋,名稱以 veth 開頭(例如 vethAQI2QT )。經過這種方式,主機能夠跟容器通訊,容器之間也能夠相互通訊。Docker 就建立了在主機和全部容器之間一個虛擬共享網絡。
Docker 沒有爲每一個容器專門定製鏡像,那麼怎麼自定義配置容器的主機名和 DNS 配置呢? 祕訣就是它利用虛擬文件來掛載到來容器的 3 個相關配置文件。
在容器中使用 mount 命令能夠看到掛載信息:
$ mount
...
/dev/disk/by-uuid/1fec...ebdf on /etc/hostname type ext4 ...
/dev/disk/by-uuid/1fec...ebdf on /etc/hosts type ext4 ...
tmpfs on /etc/resolv.conf type tmpfs ...
...
這種機制可讓宿主主機 DNS 信息發生更新後,全部 Docker 容器的 dns 配置經過 /etc/resolv.conf 文件馬上獲得更新。
若是用戶想要手動指定容器的配置,能夠利用下面的選項。
-h HOSTNAME or --hostname=HOSTNAME 設定容器的主機名,它會被寫到容器內的 /etc/hostname 和 /etc/hosts 。但它在容器外部看不到,既不會在 docker ps 中顯示,也不會在其餘的容器的 /etc/hosts 看到。
--link=CONTAINER_NAME:ALIAS 選項會在建立容器的時候,添加一個其餘容器的主機名到 /etc/hosts 文件中,讓新容器的進程可使用主機名 ALIAS 就能夠鏈接它。
--dns=IP_ADDRESS 添加 DNS 服務器到容器的 /etc/resolv.conf 中,讓容器用這個服務器來解析全部不在 /etc/hosts 中的主機名。
--dns-search=DOMAIN 設定容器的搜索域,當設定搜索域爲 .example.com 時,在搜索一個名爲 host 的 主機時,DNS 不只搜索host,還會搜索 host.example.com 。 注意:若是沒有上述最後 2 個選項, Docker 會默認用主機上的 /etc/resolv.conf 來配置容器。
容器的訪問控制,主要經過 Linux 上的 iptables 防火牆來進行管理和實現。 iptables 是 Linux 上默認的防火牆軟件,在大部分發行版中都自帶。
容器要想
訪問
外部網
絡
,須要本地系
統
的
轉發
支持。在
Linux
系
統
中,
檢查轉發
是否打開。
[root@master ~]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
若是爲 0,說明沒有開啓轉發,則須要手動打開。
$sysctl -w net.ipv4.ip_forward=1
容器之間相互訪問,須要兩方面的支持。
- 容器的網絡拓撲是否已經互聯。默認狀況下,全部容器都會被鏈接到 docker0 網橋上。
- 本地系統的防火牆軟件 -- iptables 是否容許經過。
訪問全部端口
當啓動 Docker 服務時候,默認會添加一條轉發策略到 iptables 的 FORWARD 鏈上。策略爲經過( ACCEPT )仍是禁止( DROP )取決於配置 --icc=true (缺省值)仍是 --icc=false 。固然,若是手 動指定 --iptables=false 則不會添加 iptables 規則。
可見,默認狀況下,不一樣容器之間是容許網絡互通的。若是爲了安全考慮,能夠在 /etc/default/docker文件中配置 DOCKER_OPTS=--icc=false 來禁止它
在經過 -icc=false 關閉網絡訪問後,還能夠經過 --link=CONTAINER_NAME:ALIAS 選項來訪問容器的開 放端口。
例如,在啓動 Docker 服務時,能夠同時使用 icc=false --iptables=true 參數來關閉容許相互的網絡 訪問,並讓 Docker 能夠修改系統中的 iptables 規則。
此時,系統中的 iptables 規則多是相似
$ sudo iptables -nL
...
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DROP all -- 0.0.0.0/0 0.0.0.0/0
...
以後,啓動容器( docker run )時使用 --link=CONTAINER_NAME:ALIAS 選項。Docker 會在 iptable 中爲 兩個容器分別添加一條 ACCEPT 規則,容許相互訪問開放的端口(取決於 Dockerfile 中的 EXPOSE 行)。docker
當添加了 --link=CONTAINER_NAME:ALIAS 選項後,添加了 iptables 規則
$ sudo iptables -nL
...
Chain FORWARD (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- 172.17.0.2 172.17.0.3 tcp spt:80
ACCEPT tcp -- 172.17.0.3 172.17.0.2 tcp dpt:80
DROP all -- 0.0.0.0/0 0.0.0.0/0
注意: --link=CONTAINER_NAME:ALIAS 中的 CONTAINER_NAME 目前必須是 Docker 分配的名字,或使用 --name 參數指定的名字。主機名則不會被識別
映射容器端口到宿主主機的實現
容器訪問外部實現
容器全部到外部網絡的鏈接,源地址都會被NAT成本地系統的IP地址。這是使用 iptables 的源地址假裝 操做實現的。
查看主機的 NAT 規則。
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
......
其中,上述規則將全部源地址在 172.17.0.0/16 網段,目標地址爲其餘網段(外部網絡)的流量動態僞 裝爲從系統網卡發出。MASQUERADE 跟傳統 SNAT 的好處是它能動態從網卡獲取地址.
容器容許外部訪問,能夠在 docker run 時候經過 -p 或 -P 參數來啓用。 無論用那種辦法,其實也是在本地的 iptable 的 nat 表中添加相應的規則。
使用 -p80:80 時:
Chain DOCKER (2 references)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.15:80
使用 -P 時:
$ iptables -t nat -nL
Chain DOCKER (2 references)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:49153 to:172.17.0.2
IP:host_port:container_port 或 -p IP::port 來指定容許訪問容器的主機上的 IP、接口等,以制 定更嚴格的規則。
若是但願永久綁定到某個固定的 IP 地址,能夠在 Docker 配置文件 /etc/default/docker 中指定 DOCKER_OPTS="--ip=IP_ADDRESS" ,以後重啓 Docker 服務便可生效。
配置 docker0 網橋
Docker 服務默認會建立一個 docker0 網橋(其上有一個 docker0 內部接口),它在內核層連通了其餘 的物理或虛擬網卡,這就將全部容器和本地主機都放到同一個物理網絡。
Docker 默認指定了 docker0 接口 的 IP 地址和子網掩碼,讓主機和容器之間能夠經過網橋相互通訊,它還給出了 MTU(接口容許接收的最大傳輸單元),一般是 1500 Bytes,或宿主主機網絡路由上支持的默認值。這些值均可以在服務啓動的時候進行配置。
- --bip=CIDR -- IP 地址加掩碼格式,例如 192.168.1.5/24
- --mtu=BYTES -- 覆蓋默認的 Docker mtu 配置
也能夠在配置文件中配置 DOCKER_OPTS,而後重啓服務。 因爲目前 Docker 網橋是 Linux 網橋,用戶可 以使用 brctl show 來查看網橋和端口鏈接信息。
[root@master ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.56847afe9799 no veth6278b4d
veth9321eba
vethc12c3b4
vethe54ad11
每次建立一個新容器的時候,Docker 從可用的地址段中選擇一個空閒的 IP 地址分配給容器的 eth0 端口。 使用本地主機上 docker0 接口的 IP 做爲全部容器的默認網關.安全
自定義網橋
除了默認的 docker0 網橋,用戶也能夠指定網橋來鏈接各個容器。 在啓動 Docker 服務的時候,使用 -b BRIDGE 或 --bridge=BRIDGE 來指定使用的網橋。
若是服務已經運行,那須要先中止服務,並刪除舊的網橋。
$ sudo service docker stop
$ sudo ip link set dev docker0 down
$ sudo brctl delbr docker0
而後建立一個網橋 bridge0
$ sudo brctl addbr bridge0
$ sudo ip addr add 192.168.5.1/24 dev bridge0
$ sudo ip link set dev bridge0 up
查看確認網橋建立並啓動
ip addr show bridge0
4: bridge0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state UP group default
link/ether 66:38:d0:0d:76:18 brd ff:ff:ff:ff:ff:ff
inet 192.168.5.1/24 scope global bridge0
valid_lft forever preferred_lft forever
配置
Docker
服
務
,默
認橋
接到
創
建的網
橋
上
$ echo 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker
$ sudo service docker start
啓動 Docker 服務。 新建一個容器,能夠看到它已經橋接到了 bridge0 上。 能夠繼續用 brctl show 命令查看橋接的信息。另外,在容器中可使用 ip addr 和 ip route 命令來 查看 IP 地址配置和路由信息。服務器