這節(jié)是對Docker的網(wǎng)絡(luò)行為進行概括,包括默認創(chuàng)建的所有網(wǎng)絡(luò)類型和如何創(chuàng)建自己網(wǎng)絡(luò),同時描述了如何使用網(wǎng)絡(luò)在一臺主機或者集群中
默認網(wǎng)絡(luò)
當(dāng)你安裝docker后,會自動創(chuàng)建3個網(wǎng)絡(luò)設(shè)備,你可以通過命令行查看他們
$ docker network ls
NETWORK ID NAME DRIVER
7fca4eb8c647 bridge bridge
9f904ee27bf5 none null
cf03ee007fb4 host host
這三個網(wǎng)絡(luò)設(shè)備創(chuàng)建到Docker中。當(dāng)你啟動一個容器的時候,你可以通過--network去設(shè)置容器使用的網(wǎng)絡(luò)設(shè)備
在Docker中橋接網(wǎng)絡(luò)(bridge network)是默認的,除非你通過--network=<NETWORK>選項,docker的守護進程默認會讓容器連接這個橋接網(wǎng)絡(luò)。在宿主機器中你可以通過ifconfig命令看到這個橋接網(wǎng)絡(luò)
$ 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)
再一個無網(wǎng)絡(luò)(none network)容器中,容器是沒有網(wǎng)絡(luò)設(shè)備的,可以連接這個容器,執(zhí)行如下命令:
$ 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:/#
注意:你可以按ctrl-p ctrl-q 退出容器
在一個主機網(wǎng)絡(luò)(host network)容器中,主機和容器是沒有隔離的。例如,你在容器中啟動一個服務(wù)監(jiān)聽80端口,那么在宿主機中80端口是可以訪問的。
無網(wǎng)絡(luò)(none network)和主機網(wǎng)絡(luò)(host network)在Docker中是不可以直接配置的,但是你可以配置默認橋接網(wǎng)絡(luò)像配置自定義橋接網(wǎng)絡(luò)一樣。
默認的橋接網(wǎng)絡(luò)
這個默認的橋接網(wǎng)絡(luò)(bridge network)會出現(xiàn)在所有Docker中,如果你沒有特殊設(shè)置網(wǎng)絡(luò),新的docker容器都會連接到這個橋接網(wǎng)絡(luò)(bridge network)
docker的inspect命令返回下面的信息:
$ 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"
},
"Labels": {}
}
]
運行下面兩條命令啟動兩個橋接網(wǎng)絡(luò)(bridge network)的busybox 容器
$ docker run -itd --name=container1 busybox
3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c
$ docker run -itd --name=container2 busybox
94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c
在兩個容器啟動后再次運行inspect命令,會看到兩個busybox的容器連接到網(wǎng)絡(luò)上。他們的ip地址會在宿主機器中是不同的
$ 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"
},
"Labels": {}
}
]
連接到默認橋接網(wǎng)絡(luò)容器可以通過ip地址彼此通信。docker在默認橋接網(wǎng)絡(luò)中不支持自動服務(wù)發(fā)現(xiàn)( automatic service discovery),如果你想讓容器通過容器名稱自動解析ip,你應(yīng)該創(chuàng)建自定義網(wǎng)絡(luò)。可以通過--link參數(shù)讓兩個容器連接起來,但是這個大多數(shù)時候是不推薦的。
你可以連接到一個運行的容器中,看到容器的網(wǎng)絡(luò)狀態(tài)。連接后是root權(quán)限,所以可以看見命令行是#開頭的
$ docker attach container1
root@0cb243cd1293:/# 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命令測試是否可以連接到其他容器
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命令查看/etc/hosts文件??梢钥吹饺萜髦杏蛎蚷p地址的對應(yīng)關(guān)系
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可以脫離容器的連接,你可以重復(fù)上述命令在另一個容器中.
通過--link參數(shù)可以配置hosts中的ip和容器對應(yīng)關(guān)系,在默認的橋接網(wǎng)絡(luò)中,但是這個是不推薦的。如果可能你應(yīng)該用自定義橋接網(wǎng)絡(luò)替換默認橋接網(wǎng)絡(luò)。
用戶自定義網(wǎng)絡(luò)(User-defined networks)
用戶自定義橋接網(wǎng)絡(luò)是被推薦的,用來控制哪些容器可以連接彼此,同時支持自動dns解析容器名稱和ip地址的對應(yīng)關(guān)系。Docker提供默認的網(wǎng)絡(luò)驅(qū)動去創(chuàng)建自定義網(wǎng)絡(luò)。你可以創(chuàng)建一個新的自定義橋接網(wǎng)絡(luò),覆蓋默認網(wǎng)絡(luò)或者MACVLAN(mac虛擬網(wǎng)絡(luò))。你同時可以創(chuàng)建一個網(wǎng)絡(luò)插件或者完全定制化和控制的遠程網(wǎng)絡(luò)。
You can create as many networks as you need, and you can connect a container to zero or more of these networks at any given time. In addition, you can connect and disconnect running containers from networks without restarting the container. When a container is connected to multiple networks, its external connectivity is provided via the first non-internal network, in lexical order.
如果需要你可以創(chuàng)建任意多的自定義網(wǎng)絡(luò),同時你可以在任意時間使一個容器同時連接零或多個自定義網(wǎng)絡(luò)中,同時你可以連接或者斷開一個容器的網(wǎng)絡(luò),而不用重啟容器。當(dāng)一個容器鏈接到多個網(wǎng)絡(luò)中的時候,他的外部網(wǎng)絡(luò)訪問時通過一個非內(nèi)部網(wǎng)絡(luò)提供。
下面一些章節(jié)描述了Docker內(nèi)置的所有網(wǎng)絡(luò)驅(qū)動細節(jié)
橋接網(wǎng)絡(luò)
橋接網(wǎng)絡(luò)是docker中做常用的。自定義橋接網(wǎng)絡(luò)幾乎和默認橋接網(wǎng)絡(luò)一致,只是有一些新的功能和移除了一些老的特性。下面的例子中創(chuàng)建了一些自定義橋接網(wǎng)絡(luò)和容器應(yī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": {},
"Labels": {}
}
]
$ docker network ls
NETWORK ID NAME DRIVER
9f904ee27bf5 none null
cf03ee007fb4 host host
7fca4eb8c647 bridge bridge
c5ee82f76de3 isolated_nw bridge
當(dāng)你創(chuàng)建了網(wǎng)絡(luò),通過--network=<NETWORK>參數(shù),你可以讓容器應(yīng)用這個網(wǎng)絡(luò)
$ docker run --network=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": {},
"Labels": {}
}
]
在同一臺Docker宿主機中和這個網(wǎng)絡(luò)中的所有容器,可以快速的彼此通信。但是在這個網(wǎng)絡(luò)外的容器是不可以訪問的。

在自定義橋接網(wǎng)絡(luò)中 link是不允許的。在這個自定義橋接網(wǎng)絡(luò)中你可以導(dǎo)出和發(fā)布這些容器的端口,你這樣可以在自定義橋接網(wǎng)絡(luò)外訪問這些端口。

如果你想創(chuàng)建一個小型的網(wǎng)絡(luò)在單個宿主機上,自定義橋接網(wǎng)絡(luò)是很有用的。如果想創(chuàng)建一個大型網(wǎng)絡(luò)結(jié)構(gòu),那么需要通過創(chuàng)建覆蓋網(wǎng)絡(luò)(overlay network)。
docker_gwbridge網(wǎng)關(guān)橋接網(wǎng)絡(luò)
docker_gwbridge網(wǎng)關(guān)橋接網(wǎng)絡(luò)是一個本地橋接網(wǎng)絡(luò),由docker在兩個不同的主機環(huán)境中自動創(chuàng)建的
- 當(dāng)你初始化或者叫加入一個集群,Docker會創(chuàng)建一個docker_gwbridge網(wǎng)絡(luò),用來集群中的不同宿主機節(jié)點的通信
- 當(dāng)docker容器的網(wǎng)絡(luò)中沒有一個提供外部鏈接時,Docker鏈接這些容器到docker_gwbridge網(wǎng)絡(luò)用來和外部容器通信,這樣這些容器就可以鏈接到外部網(wǎng)絡(luò)或者其它的集群節(jié)點。
你可以創(chuàng)建一個自定義配置的docker_gwbridge網(wǎng)絡(luò),下面的例子展示如何創(chuàng)建一個自定義配置的docker_gwbridge網(wǎng)絡(luò)
$ docker network create --subnet 172.30.0.0/16 \
--opt com.docker.network.bridge.name=docker_gwbridge \
--opt com.docker.network.bridge.enable_icc=false \
docker_gwbridge
當(dāng)你使用覆蓋網(wǎng)絡(luò)時,docker_gwbridge 網(wǎng)關(guān)橋接網(wǎng)絡(luò)總會出現(xiàn)。
覆蓋網(wǎng)絡(luò)在集群模式中
在集群模式中,不需要key-value緩存,你可以創(chuàng)建一個覆蓋網(wǎng)絡(luò)在一個集群管理節(jié)點。在集群中所有節(jié)點都可以訪問覆蓋網(wǎng)絡(luò)。當(dāng)你在覆蓋網(wǎng)絡(luò)中創(chuàng)建一個服務(wù),管理節(jié)點可以自動擴展覆蓋網(wǎng)絡(luò)到其它集群節(jié)點。
學(xué)習(xí)更多關(guān)于docker集群模式可以看 集群模式預(yù)覽.
下面是如何創(chuàng)建一個覆蓋網(wǎng)絡(luò)并用它作為集群服務(wù)的網(wǎng)絡(luò)
$ docker network create \
--driver overlay \
--subnet 10.0.9.0/24 \
my-multi-host-network
400g6bwzd68jizzdx5pgyoe95
$ docker service create --replicas 2 --network my-multi-host-network --name my-web nginx
716thylsndqma81j6kkkb5aus
只有集群服務(wù)可以連接覆蓋網(wǎng)絡(luò),單獨的容器是不可以的。更多關(guān)于集群的信息,請查看 Docker集群模式和覆蓋網(wǎng)絡(luò)的安全 和 在覆蓋網(wǎng)絡(luò)中連接容器.
覆蓋網(wǎng)絡(luò)在非集群模式中
如果你的Docker機器不是用在集群模式中,那么覆蓋網(wǎng)絡(luò)需要一個key-value緩存服務(wù)。支持的key-value緩存服務(wù)包括Consul, Etcd,和 ZooKeeper (Distributed store).在創(chuàng)建這個覆蓋網(wǎng)絡(luò)之前,你必須安裝和配置你的key-value緩存服務(wù)。在宿主機器必須可以上網(wǎng),而且key-value緩存服務(wù)是可以訪問的。
注意: Docker在集群模式中是不需要key-value緩存服務(wù)的
不在集群模式下使用覆蓋網(wǎng)絡(luò)是不推薦的。但是在單宿主機中和Docker開發(fā)者這種模式可能很有用。在未來它很可能被刪掉。如果你需要在這種模式中啟動,可以查看 介紹.
自定義網(wǎng)絡(luò)插件
如果你的需求上述網(wǎng)絡(luò)都不能滿足,那么你可以根據(jù)docker的插件基礎(chǔ)開發(fā)自己的網(wǎng)絡(luò)插件。這個插件將會單獨運行在一個進程里。用網(wǎng)絡(luò)插件是一個高級的課題。
網(wǎng)絡(luò)插件跟其他docker插件有一樣的規(guī)則和約束。所有的插件都用同一套API,有同樣的生命周期,包括安裝,啟動,停止,和激活。
一旦你創(chuàng)建并安裝了一個自定義網(wǎng)絡(luò)插件,你可以通過driver參數(shù)指定通過插件創(chuàng)建你需要的網(wǎng)絡(luò)。
$ docker network create --driver weave mynet
你可以檢查一個網(wǎng)絡(luò),容器跟網(wǎng)絡(luò)的鏈接和斷開鏈接,或者移除他。網(wǎng)絡(luò)插件可能有自己的特殊依賴,檢查插件的文檔獲取信息。寫網(wǎng)絡(luò)插件的更多信息打開鏈接 docker擴展 和寫一個網(wǎng)絡(luò)插件.
內(nèi)置dns服務(wù)
docker守護進程會運行一個內(nèi)置的dns服務(wù),用來提供在同一個網(wǎng)絡(luò)下容器之間可以通過域名(容器名稱)解析彼此,即把容器名解析成ip。如果內(nèi)置的dns服務(wù)器不能解析,則會交給外部主機的dns解析。當(dāng)容器創(chuàng)建的時候,內(nèi)置的dns服務(wù)的ip是127.0.0.11 容器域名會列在resolv.conf文件里。獲取更多關(guān)于內(nèi)置dns服務(wù)的信息,看 內(nèi)置dns服務(wù)在自定義網(wǎng)絡(luò)的使用
暴露和發(fā)布端口
docker的網(wǎng)絡(luò)環(huán)境中,有兩種方式開放端口,發(fā)布端口和暴露端口。在默認橋接網(wǎng)絡(luò)和自定義網(wǎng)絡(luò)都可以。
- 暴露端口通過EXPOSE關(guān)鍵字在Dockerfile或者通過docker run --expose參數(shù)
- 發(fā)布端口通過PUBLISH關(guān)鍵字在Dockerfile中,或者通過docker run的--publish參數(shù)。docker會根據(jù)這些參數(shù)或者關(guān)鍵字打開端口給網(wǎng)絡(luò)接口。當(dāng)發(fā)布端口后,宿主機會有一個大于30000的端口與之對應(yīng),除非你在運行時指定宿主機哪個端口與之對應(yīng)。 你不能在Dockerfile中指定對應(yīng)端口,因為不能確定宿主機那個端口是否可用。
下面是發(fā)布80端口的例子,會有隨機的一個大于30000的端口與之對應(yīng)
$ docker run -it -p 80 nginx
$ docker ps
64879472feea nginx "nginx -g 'daemon ..." 43 hours ago
Up About a minute 443/tcp, 0.0.0.0:32768->80/tcp blissful_mclean
這個例子是指定80端口與8080端口對應(yīng),如果8080不可用,會失敗。
$ docker run -it -p 80:8080 nginx
$ docker ps
b9788c7adca3 nginx "nginx -g 'daemon ..." 43 hours ago
Up 3 seconds 80/tcp, 443/tcp, 0.0.0.0:80->8080/tcp goofy_brahmagupta
鏈接Links
在Docker提供自定義網(wǎng)絡(luò)前,你只能通過--link功能讓容器間網(wǎng)通過容器名稱解析ip地址,也讓兩個容器可以互相通信?,F(xiàn)在你應(yīng)該避免使用--link標記。
當(dāng)你創(chuàng)建links時,它和自定義橋接網(wǎng)絡(luò)是不同的。更多信息查看 link功能在默認橋接網(wǎng)絡(luò)的傳統(tǒng)鏈接 和 用戶自定義橋接網(wǎng)絡(luò)容器通信自定義橋接網(wǎng)絡(luò)中容器通信