Docker Engine -> User guide -> Network configuration -> Docker container networking
了解Docker容器網(wǎng)絡(luò)
利用Docker的網(wǎng)絡(luò)功能去構(gòu)件一個(gè)web app會(huì)更安全。Docker的network可以為容器提供一個(gè)完全隔離的網(wǎng)絡(luò)環(huán)境。能夠掌控運(yùn)行的app網(wǎng)絡(luò)對(duì)你是非常重要的。Docker的容器網(wǎng)絡(luò)可以給予你這個(gè)掌控網(wǎng)絡(luò)的能力。
這一節(jié)關(guān)于Docker Engine原生提供的默認(rèn)的網(wǎng)絡(luò)行為。描述了默認(rèn)創(chuàng)建的或是屬于你自己的用戶自定義的network類(lèi)型,還有當(dāng)創(chuàng)建一個(gè)network在單主機(jī)或是一個(gè)跨主機(jī)集群中需要的資源。
默認(rèn)的網(wǎng)絡(luò)
當(dāng)你安裝Docker后,它會(huì)自動(dòng)創(chuàng)建三個(gè)network,你可以使用命令:docker network ls
列出它們:
$ docker network ls
NETWORK ID NAME DRIVER
7fca4eb8c647 bridge bridge
9f904ee27bf5 none null
cf03ee007fb4 host host
從歷史上看,這三個(gè)network是Docker實(shí)現(xiàn)的一部分。當(dāng)你運(yùn)行一個(gè)container時(shí),你可以用--net
標(biāo)志去指定這個(gè)container運(yùn)行在哪一種network上。這三種network你都可以使用。
這個(gè)bridge
network 代表所有安裝了Docker的主機(jī)的docker0
network。除非使用docker run --set=<NETWORK>
選項(xiàng)指定一個(gè)其它的network,否則Docker daemon會(huì)默認(rèn)使用這個(gè)network連接contrainer。你可以使用系統(tǒng)的ifconfig
命令查看主機(jī)的network stack中的docker0:
$ ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:47:bc:3a:eb
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:47ff:febc:3aeb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1
RX packets:17 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1100 (1.1 KB) TX bytes:648 (648.0 B)
這個(gè)none
network 會(huì)將容器添加到一個(gè) container-specific 的 network stack。這個(gè)容器缺少一個(gè)network interface。如果你想連接這個(gè)容器并查看它的stack,你可以這樣:
// use the commond "docker attach <container-name>" to attaching this container
$ docker attach nonenetcontainer
root@0cb243cd1293:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
root@0cb243cd1293:/# ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
root@0cb243cd1293:/#
注意:你可以通過(guò)
CTRL-p CTRL-q
脫離容器。
這個(gè)host
network,將container添加到主機(jī)的network stack。你會(huì)發(fā)現(xiàn)這個(gè)container的網(wǎng)絡(luò)配置與主機(jī)是一致的。
除了bridge
network,你可能不需要其他的默認(rèn)network。雖然你可以列出并查看這些network,但是你不能刪除它們。這些是Docker所需要的。然而你可以添加屬于你的自定義network,當(dāng)你不再需要這些network的時(shí)候你可以刪除它們。在你了解更多關(guān)于創(chuàng)建屬于你自己的network之前,默認(rèn)的bridge
network還是值得你看看的。
詳解brigde
network
這個(gè)默認(rèn)的bridge
network存在于所有的Docker主機(jī)。docker network inspect
命令可以返回關(guān)于network的信息:
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.17.0.1/16",
"Gateway": "172.17.0.1"
}
]
},
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "9001"
}
}
]
Docker Engine 會(huì)自動(dòng)創(chuàng)建一個(gè) Subnet
和Gateway
在這個(gè)network。docker run
命令自動(dòng)添加一個(gè)新的container到這個(gè)network:
$ docker run -itd --name=container1 busybox
3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c
$ docker run -itd --name=container2 busybox
94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c
在啟動(dòng)兩個(gè)新的container之后,查看一下bridge
網(wǎng)絡(luò)。這兩個(gè)容器的id會(huì)出現(xiàn)在 Containers
這個(gè)字段中:
$ docker network inspect bridge
{[
{
"Name": "bridge",
"Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.17.0.1/16",
"Gateway": "172.17.0.1"
}
]
},
"Containers": {
"3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c": {
"EndpointID": "647c12443e91faf0fd508b6edfe59c30b642abb60dfab890b4bdccee38750bc1",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c": {
"EndpointID": "b047d090f446ac49747d3c37d63e4307be745876db7f0ceef7b311cbba615f48",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "9001"
}
}
]
上面是 docker network inspect
命令根據(jù)給定的network回顯的這個(gè)network已連接的容器和它的一些網(wǎng)絡(luò)資源。在這個(gè)默認(rèn)的network中的container可以利用IP地址相互通信。在默認(rèn)的bridge
network中Docker不支持自動(dòng)的服務(wù)發(fā)現(xiàn)。如果你的container想要通過(guò)其他container的name在這個(gè)默認(rèn)的bridge
network中通行,你必須通過(guò)docker run --linke
選項(xiàng)來(lái)實(shí)現(xiàn)。
你可以attach
一個(gè)正在運(yùn)行的container并查看它的網(wǎng)絡(luò)配置:
$ docker attach container1
root@0cb243cd1293:/# ifconfig
ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1
RX packets:16 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1296 (1.2 KiB) TX bytes:648 (648.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
然后使用ping
命令來(lái)做一個(gè)3秒測(cè)試,測(cè)試這個(gè)在bridge
network上的container的連通性。
root@0cb243cd1293:/# ping -w3 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.096 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.074 ms
--- 172.17.0.3 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.074/0.083/0.096 ms
最后,使用cat
命令來(lái)檢查container1的網(wǎng)絡(luò)配置:
root@0cb243cd1293:/# cat /etc/hosts
172.17.0.2 3386a527aa08
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
使用CTRL-p CTRL-q
脫離container1后,連接到container2并重復(fù)這三個(gè)命令。
$ docker attach container2
root@0cb243cd1293:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03
inet addr:172.17.0.3 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:3/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1
RX packets:15 errors:0 dropped:0 overruns:0 frame:0
TX packets:13 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1166 (1.1 KiB) TX bytes:1026 (1.0 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
root@0cb243cd1293:/# ping -w3 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.067 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.075 ms
64 bytes from 172.17.0.2: seq=2 ttl=64 time=0.072 ms
--- 172.17.0.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.067/0.071/0.075 ms
/ # cat /etc/hosts
172.17.0.3 94447ca47985
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
這個(gè)默認(rèn)的橋接網(wǎng)絡(luò)docker0
支持使用端口映射和通過(guò)docker run --link
使兩個(gè)在docker0
中的container可以彼此通信。這些方式設(shè)置起來(lái)很麻煩并且容易出錯(cuò)。雖然你仍然可以這樣使用,但是最好避免這樣,更推薦你去定義你自己的橋接網(wǎng)路來(lái)替代它。
自定義的network
你可以創(chuàng)建屬于你的自定義network來(lái)更好的隔離container。為了創(chuàng)建這些network,Docker提供了一些默認(rèn)的network drivers。你可以創(chuàng)建一個(gè)新的bridge network
或者overlay network
。你也可以創(chuàng)建一個(gè)network plugin
或是一個(gè)remote network
。
你可以創(chuàng)建多個(gè)網(wǎng)絡(luò)。可以添加一個(gè)container到多個(gè)網(wǎng)絡(luò)。container只能在這個(gè)網(wǎng)絡(luò)中通行不能跨越這個(gè)網(wǎng)絡(luò)。一個(gè)container可以附著到兩個(gè)network中,并分別與這兩個(gè)network中的container成員通信。
接下來(lái)的幾節(jié)更加詳細(xì)的描述每一個(gè)Docker內(nèi)建的網(wǎng)絡(luò)驅(qū)動(dòng)。
橋接網(wǎng)絡(luò)(bridge network)
很容易就可以創(chuàng)建一個(gè)自定義的bridge
模式的network。這個(gè)network和docker0
很像。這里又一些已添加的功能和一些已經(jīng)不可用的舊功能。
$ docker network create --driver bridge isolated_nw
1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b
$ docker network inspect isolated_nw
[
{
"Name": "isolated_nw",
"Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.21.0.0/16",
"Gateway": "172.21.0.1/16"
}
]
},
"Containers": {},
"Options": {}
}
]
$ docker network ls
NETWORK ID NAME DRIVER
9f904ee27bf5 none null
cf03ee007fb4 host host
7fca4eb8c647 bridge bridge
c5ee82f76de3 isolated_nw bridge
創(chuàng)建這個(gè)network之后,你可以使用這個(gè)創(chuàng)建的network通過(guò)docker run --net=<NETWORK>
選項(xiàng)啟動(dòng)一個(gè)container。
$ docker run --net=isolated_nw -itd --name=container3 busybox
8c1a0a5be480921d669a073393ade66a3fc49933f08bcc5515b37b8144f6d47c
$ docker network inspect isolated_nw
[
{
"Name": "isolated_nw",
"Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{}
]
},
"Containers": {
"8c1a0a5be480921d669a073393ade66a3fc49933f08bcc5515b37b8144f6d47c": {
"EndpointID": "93b2db4a9b9a997beb912d28bcfc117f7b0eb924ff91d48cfa251d473e6a9b08",
"MacAddress": "02:42:ac:15:00:02",
"IPv4Address": "172.21.0.2/16",
"IPv6Address": ""
}
},
"Options": {}
}
]
推入到這個(gè)network的container必須存在于同一個(gè)Docker主機(jī)。每一個(gè)network中的container可以立即與在這個(gè)network中的其它c(diǎn)ontainer通信。這個(gè)network將外部網(wǎng)絡(luò)與其內(nèi)部的container隔離開(kāi)來(lái)。

用戶自定義的橋接網(wǎng)絡(luò)是不支持link
的。你可以將這個(gè)network中開(kāi)放的container的端口暴露出來(lái)。如果你想使一部分橋接網(wǎng)絡(luò)開(kāi)放給外部網(wǎng)絡(luò)這是很有用的。

一個(gè)bridge
network在單主機(jī)的相對(duì)較小的網(wǎng)絡(luò)環(huán)境中是很有用的一種解決方案。然而當(dāng)需要?jiǎng)?chuàng)建一個(gè)很龐大的網(wǎng)絡(luò)環(huán)境的時(shí)候你需要一個(gè)overlay
network.
覆蓋網(wǎng)絡(luò)(overlay network)
Docker的overlay
network 驅(qū)動(dòng)原生就支持一個(gè)多主機(jī)網(wǎng)絡(luò)。這種支持是在libnetwork
的幫助下完成的,一個(gè)內(nèi)建的基于VXLAN
的overlay
network驅(qū)動(dòng)還有Docker的libkv
庫(kù)。
這個(gè)overlay
network需要一個(gè)有效的key-value
存貯服務(wù)。當(dāng)前,Docker的libkv
支持Consul,Etcd和ZooKeeper(分布式存貯)。在創(chuàng)建這樣一個(gè)網(wǎng)絡(luò)之前你必須安裝配置一個(gè)你選用的key-value
存貯服務(wù)。你創(chuàng)建network的Docker主機(jī)必須能夠與服務(wù)通信。

這個(gè)network中的主機(jī)必須運(yùn)行Docker Engine實(shí)例。最簡(jiǎn)單的方式是為每個(gè)主機(jī)提供一個(gè)Docker Machine。

你應(yīng)當(dāng)在每個(gè)主機(jī)上打開(kāi)下面的端口。
Protocol | Port | Description |
---|---|---|
udp | 4789 | Data plane(VXLAN) |
tcp/udp | 7946 | Control plane |
你的key-value
存貯服務(wù)可能需要額外的端口。檢查你的供應(yīng)商文檔然后打開(kāi)所有需要的端口。