赞
踩
翻译自docker官方文档,原文:https://docs.docker.com/engine/userguide/networking/work-with-networks/
这篇文章提供了几个你可以用来和docker网络及其中的容器进行交互的网络子命令的例子。这些命令可以通过docker引擎的命令行接口(CLI)使用,命令如下:
docker network create
docker network connect
docker network ls
docker network rm
docker network disconnect
docker network inspect
虽然不是必须的,但在尝试本章中介绍的例子之前读一下docker网络简介的文章(已翻译,就是这篇:http://blog.csdn.net/zlw01234/article/details/79237651)是有好处的。
下面的例子用的是默认的bridge网络,所以你可以直接开始实验。要用overlay式网络尝试这些例子,请查看另一篇文章(未翻译,原文章地址:https://docs.docker.com/engine/userguide/networking/get-started-overlay/)。
当你安装docker的时候,docker引擎会自动创建一个bridge
网络。这个网络会和叫做docker0
的网桥(在宿主机上,可以通过ifconfig查看)通信,而且docker引擎已经连到docker0
上了。除了这个网络,你也可以创建你自己的桥接式(bridge
)或overlay
式网络。
bridge
式网络只能用于安装有docker引擎的单主机上。而overlay
式网络可以连通多台有docker引擎的主机。当你运行docker network create
命令并且只提供了一个网络名时,它会给你创建一个bridge式网络。
$ docker network create simple-network
69568e6336d8c96bbf57869030919f7c69524f71183b44d80948bd3927c87f6a
$ docker network inspect simple-network
[
{
"Name": "simple-network",
"Id": "69568e6336d8c96bbf57869030919f7c69524f71183b44d80948bd3927c87f6a",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.22.0.0/16",
"Gateway": "172.22.0.1"
}
]
},
"Containers": {},
"Options": {},
"Labels": {}
}
]

和bridge式网络不同的是,overlay式网络在创建前需要一些先决条件,这些条件是:
支持overlay式网络的dockerd选项有:
--cluster-store
--cluster-store-opt
--cluster-advertise
当你创建网络时,引擎会自动给这个网络创建一个不重叠的子网(译者注:指在docker管理的所有网络中不重叠)。你可以用--subnet
选项来直接指定子网并覆盖默认值。在bridge
式网络中,你只能指定一个子网,在overlay
式网络中你可以指定多个子网。
注意:强烈建议在创建网络时使用--subnet
参数。如果没指定,docker守护进程会自动从网络中选择并分配一个子网,而这个子网可能覆盖你硬件中不由docker管理的另一个子网。这种覆盖现象可能导致容器连到这个网络时出问题或失败。
除了--subnet
参数,你还可以指定--getway
,--ip-range
和--aux-address
参数。
$ docker network create -d overlay \
--subnet=192.168.0.0/16 \
--subnet=192.170.0.0/16 \
--gateway=192.168.0.100 \
--gateway=192.170.0.100 \
--ip-range=192.168.1.0/24 \
--aux-address="my-router=192.168.1.5" --aux-address="my-switch=192.168.1.6" \
--aux-address="my-printer=192.170.1.5" --aux-address="my-nas=192.170.1.6" \
my-multihost-network
要确保你的子网没有重叠,否则创建网络会失败,docker会返回一个错误。
当创建自定义网络时,可以传递一些额外的参数。bridge
式网络接受的参数有:
参数 | 等价于 | 描述 |
---|---|---|
com.docker.network.bridge.name | - | 创建Linux网桥设备时的网桥名称 |
com.docker.network.bridge.enable_ip_masquerade | --ip-masq | 是否允许IP伪装 |
com.docker.network.bridge.enable_icc | --icc | 是否允许网络内的容器连通 |
com.docker.network.bridge.host_binding_ipv4 | --ip | 绑定容器端口时默认的IP |
com.docker.network.driver.mtu | --mtu | 设置容器网络的MTU |
com.docker.network.driver.mtu
参数也适用于overlay
式的网络。
下面的参数可以在创建任何形式的网络时传给docker network create
:
参数 | 等价于 | 描述 |
---|---|---|
--internal | - | 限制外部访问到网络 |
--ipv6 | --ipv6 | 允许IPv6的网络 |
下面的例子使用-o
参数指定了特定的当绑定端口时可用的IP地址,然后用docker network inspect
检查网络,最后把一个新的容器添加到这个网络。记得把例子中的172.23.0.1
替换成你宿主机所在网络中可用的IP地址。
$ docker network create -o "com.docker.network.bridge.host_binding_ipv4"="172.23.0.1" my-network
b1a086897963e6a2e7fc6868962e55e746bee8ad0c97b54a5831054b5f62672a
$ docker network inspect my-network
[
{
"Name": "my-network",
"Id": "b1a086897963e6a2e7fc6868962e55e746bee8ad0c97b54a5831054b5f62672a",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.23.0.0/16",
"Gateway": "172.23.0.1"
}
]
},
"Containers": {},
"Options": {
"com.docker.network.bridge.host_binding_ipv4": "172.23.0.1"
},
"Labels": {}
}
]
$ docker run -d -P --name redis --network my-network redis
bafb0c808c53104b2c90346f284bda33a69beadcab4fc83ab8f2c5a4410cd129
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bafb0c808c53 redis "/entrypoint.sh redis" 4 seconds ago Up 3 seconds 172.23.0.1:32770->6379/tcp redis

你可以把已存在的容器连到一个或多个网络中。一个容器可以连到多个使用不同网络驱动的网络。一旦连上,容器就能用其他容器的IP地址或容器名与之通信。
对于overlay式网络或支持多主机互联的自定义插件来说,不同主机上的连到同一个多主机网络的容器也能以相同的方式进行通信。
下面的例子使用了6个容器,当你需要他们的时候会指导你创建的。
1.首先,创建并运行两个容器container1
和container2
:
$ docker run -itd --name=container1 busybox
18c062ef45ac0c026ee48a83afa39d25635ee5f02b58de4abc8f467bcaa28731
$ docker run -itd --name=container2 busybox
498eaaaf328e1018042c04b2de04036fc04719a6e39a097a4f4866043a2c2152
2.创建一个用于测试的隔离的bridge式网络:
$ docker network create -d bridge --subnet 172.25.0.0/16 isolated_nw
06a62f1c73c4e3107c0f555b7a5f163309827bfbbf999840166065a8f35455a8
3.把container2
连到网络,并检查(inspect)网络来检查连通性:
$ docker network connect isolated_nw container2
$ docker network inspect isolated_nw
[
{
"Name": "isolated_nw",
"Id": "06a62f1c73c4e3107c0f555b7a5f163309827bfbbf999840166065a8f35455a8",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.25.0.0/16",
"Gateway": "172.25.0.1/16"
}
]
},
"Containers": {
"90e1f3ec71caf82ae776a827e0712a68a110a3f175954e5bd4222fd142ac9428": {
"Name": "container2",
"EndpointID": "11cedac1810e864d6b1589d92da12af66203879ab89f4ccd8c8fdaa9b1c48b1d",
"MacAddress": "02:42:ac:19:00:02",
"IPv4Address": "172.25.0.2/16",
"IPv6Address": ""
}
},
"Options": {}
}
]

我们注意到container2
被自动分配了一个IP。由于你创建网络时指定了--subnet
,IP会从这个子网中选取。
提醒一下,container1
只加入了默认的bridge
网络。
4.启动第三个容器,这次用--ip
参数给它指定一个IP,再在docker run
命令中用--network
参数把它连到isolated_nw
中:
$ docker run --network=isolated_nw --ip=172.25.3.3 -itd --name=container3 busybox
467a7863c3f0277ef8e661b38427737f28099b61fa55622d6c30fb288d88c551
只要一个IP地址是子网的一部分,你就可以把这个IP指定给一个要连到该子网的容器,通过--ip
或--ip6
选项。当你使用一个用户定义的网络时,用这种方式指定IP地址的话,这个配置会作为容器的配置的一部分被保护起来,并且在容器重新启动时会生效。用非用户定义的网络(docker自带的)时,分配的IP不会被保存,因为不能保证docker守护进程重启后容器所在子网不变,除非使用用户定义的网络。
5.检查container3
所用的网络资源,下面的显示为了简明做了删减:
$ docker inspect --format='' container3
{"isolated_nw":
{"IPAMConfig":
{
"IPv4Address":"172.25.3.3"},
"NetworkID":"1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
"EndpointID":"dffc7ec2915af58cc827d995e6ebdc897342be0420123277103c40ae35579103",
"Gateway":"172.25.0.1",
"IPAddress":"172.25.3.3",
"IPPrefixLen":16,
"IPv6Gateway":"",
"GlobalIPv6Address":"",
"GlobalIPv6PrefixLen":0,
"MacAddress":"02:42:ac:19:03:03"}
}
}
}

由于你启动container3
的时候把它连到isolated_nw
里了,它就不再连到默认的bridge
网络中了。
6.检查container2
所用的网络资源,如果你安装了python,你可以美化输出:
$ docker inspect --format='' container2 | python -m json.tool
{
"bridge": {
"NetworkID":"7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812",
"EndpointID": "0099f9efb5a3727f6a554f176b1e96fca34cae773da68b3b6a26d046c12cb365",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAMConfig": null,
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:03"
},
"isolated_nw": {
"NetworkID":"1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
"EndpointID": "11cedac1810e864d6b1589d92da12af66203879ab89f4ccd8c8fdaa9b1c48b1d",
"Gateway": "172.25.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAMConfig": null,
"IPAddress": "172.25.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:19:00:02"
}
}

我们注意到container2
属于两个网络。你启动它的时候它加入了默认的bridge
网络,然后你在第三步的时候又把它连到了isolated_nw
.
7.用docker attach
命令连到正在运行的container2
,并检查它的网络:
$ docker attach container2
用ifconfig
命令检查容器的网络。你应该会看到两个以太网接口,一个是默认的bridge
网络,另一个是isolated_nw
网络。
# 原文确实有sudo,但我试的时候提示sudo:not found,把sudo去掉就行
$ sudo ifconfig -a
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:8 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:648 (648.0 B) TX bytes:648 (648.0 B)
eth1 Link encap:Ethernet HWaddr 02:42:AC:15:00:02
inet addr:172.25.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe19:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 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:648 (648.0 B) 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)

8.docker内置的DNS服务提供连到指定网络的容器的名字的解析。这意味着任何容器可以通过容器名ping通同一网络内的其他容器。在container2
内,你能用container3
的容器名ping通它:
/ # ping -w 4 container3
PING container3 (172.25.3.3): 56 data bytes
64 bytes from 172.25.3.3: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.25.3.3: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.25.3.3: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.25.3.3: seq=3 ttl=64 time=0.097 ms
--- container3 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms
这个功能在默认的bridge
网络中不可用。container1
和container2
都连到了bridge
网络,但你不能在container2
中用容器名ping通container1
:
/ # ping -w 4 container1
ping: bad address 'container1'
你还是可以直接用IPping通container1
:
/ # ping -w 4 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.095 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
64 bytes from 172.17.0.2: seq=3 ttl=64 time=0.101 ms
--- 172.17.0.2 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.072/0.085/0.101 ms
用CTRL-p CTRL-q
来离开container2
并让它保持运行。
9.现在,container2
同时连到了bridge
和isolated_nw
,所以它能和container1
和container3
通信。但是container1
和container3
没有公共的网络,所以他们不能通信。要验证这个,可以attach
到container3
然后尝试用IP来pingcontainer1
.
$ docker attach container3
$ ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
^C
--- 172.17.0.2 ping statistics ---
10 packets transmitted, 0 packets received, 100% packet loss
用CTRL-p CTRL-q
来离开container3
并让它保持运行。
你甚至可以把一个没在运行的容器连到一个网络。但是,docker network inspect
只会显示正在运行的容器的信息。
在你完成基础容器网络示例后,container2
可以自动解析container3
的容器名,因为他们都连到了isloated_nw
网络。但是,连到默认的bridge
网络的容器不能解析彼此的容器名。如果你需要bridge
网络中的容器能够互联,你需要使用遗留的link
特性。这是--link
参数唯一推荐的使用场景。强烈建议你使用用户定义的网络。
使用遗留的link
特性会在默认的bridge
网络间通信中增加以下特性:
--link=CONTAINER-NAME:ALIAS
--icc=false
)要重申一下,当你使用用户定义的网络时,所有这些特性都是默认提供的,完全不用额外的配置。另外,你还能得到动态连接或断开多个网络的能力。
--link
参数给被连接的容器指定别名下面的例子简要介绍了任何使用--link
。
1.接着上面的例子,创建一个新容器container4
,把它连到isolated_nw
网络上。另外,用--link
参数把它连到container5
(还不存在!)。
$ docker run --network=isolated_nw -itd --name=container4 --link container5:c5 busybox
01b5df970834b77a9eadbaff39051f237957bd35c4c56f11193e0594cfd5117c
这有点奇怪,因为container5
还不存在。当container5
被创建的时候,container4
可以用c5
这个名字解析出container5
的IP地址。
注意:任何用遗留的link特性创建的容器间的连接天生都是静态的,而且是把别名硬关联到容器的。它不能处理被连接的容器重启的情况。而在用户定义的网络中能用的新的link特性支持动态链接,而且能处理被连接的容器重启和IP变化的情况。
由于你还没有创建容器container5
,尝试ping它会报错。连到container4
并尝试pingcontainer5
和c5
:
$ docker attach container4
$ ping container5
ping: bad address 'container5'
$ ping c5
ping: bad address 'c5'
用CTRL-p CTRL-q
来离开container4
并让它保持运行。
2.创建另一个容器container5
,用别名c4
连到container4
:
$ docker run --network=isolated_nw -itd --name=container5 --link container4:c4 busybox
72eccf2208336f31e9e33ba327734125af00d1e1d2657878e2ee8154fbb23c7a
现在连到container4
,尝试pingcontaienr5
和c5
:
$ docker attach container4
/ # ping -w 4 c5
PING c5 (172.25.0.5): 56 data bytes
64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms
--- c5 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms
/ # ping -w 4 container5
PING container5 (172.25.0.5): 56 data bytes
64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms
--- container5 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms

用CTRL-p CTRL-q
来离开container4
并让它保持运行。
3.最后,连到container5
并验证你可以ping通container4
:
$ docker attach container5
/ # ping -w 4 c4
PING c4 (172.25.0.4): 56 data bytes
64 bytes from 172.25.0.4: seq=0 ttl=64 time=0.065 ms
64 bytes from 172.25.0.4: seq=1 ttl=64 time=0.070 ms
64 bytes from 172.25.0.4: seq=2 ttl=64 time=0.067 ms
64 bytes from 172.25.0.4: seq=3 ttl=64 time=0.082 ms
--- c4 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.065/0.070/0.082 ms
/ # ping -w 4 container4
PING container4 (172.25.0.4): 56 data bytes
64 bytes from 172.25.0.4: seq=0 ttl=64 time=0.065 ms
64 bytes from 172.25.0.4: seq=1 ttl=64 time=0.070 ms
64 bytes from 172.25.0.4: seq=2 ttl=64 time=0.067 ms
64 bytes from 172.25.0.4: seq=3 ttl=64 time=0.082 ms
--- container4 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.065/0.070/0.082 ms

用CTRL-p CTRL-q
来离开container5
并让它保持运行。
当你连接容器时,不管是用遗留的link
方法还是自定义的网络,你指定的别名都只对所指定的容器有意义,而且在默认的bridge
网络中对其他容器都没用。
另外,如果一个容器属于多个网络,给定的一个连接时的别名只能限定在一个网络。因此,一个容器能在不同网络中指定不同的别名,而且别名对不在同一网络内的容器不可见。
下面的例子说明了这些情况:
1.创建一个叫local_alias
的网络:
$ docker network create -d bridge --subnet 172.26.0.0/24 local_alias
76b7dc932e037589e6553f59f76008e5b76fa069638cd39776b890607f567aaa
2.接下来,把容器container4
和container5
连到网络local_alias
,并指定别名:foo
和bar
:
$ docker network connect --link container5:foo local_alias container4
$ docker network connect --link container4:bar local_alias container5
3.进入container4
并尝试用别名foo
来pingcontainer4
(没错,就是它自己)(译者注:这里很奇怪,foo应该是container5的别名,而且我试的时候确实解析到的是container5的IP),然后尝试用别名c5
来pingcontainer5
:
$ docker attach container4
/ # ping -w 4 foo
PING foo (172.26.0.3): 56 data bytes
64 bytes from 172.26.0.3: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.26.0.3: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.26.0.3: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.26.0.3: seq=3 ttl=64 time=0.097 ms
--- foo ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms
/ # ping -w 4 c5
PING c5 (172.25.0.5): 56 data bytes
64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms
--- c5 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms

两次都ping通了,但经过但子网不同,证明走了不同的网络。
用CTRL-p CTRL-q
来离开container4
并让它保持运行。
4.把container5
从isolated_nw
中断开,再连到container4
并尝试pingc5
和foo
:
$ docker network disconnect isolated_nw container5
$ docker attach container4
/ # ping -w 4 c5
ping: bad address 'c5'
/ # ping -w 4 foo
PING foo (172.26.0.3): 56 data bytes
64 bytes from 172.26.0.3: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.26.0.3: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.26.0.3: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.26.0.3: seq=3 ttl=64 time=0.097 ms
--- foo ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms

你不能再从isolated_nw
网络到达container5
了。但你还可以通过别名foo
到达container4
(从container4
)(译者注:跟上面一样,我觉得foo是container5的别名,所以这两处都应该是到达container5)。
用CTRL-p CTRL-q
来离开container4
并让它保持运行。
docker network
的限制虽然docker network
是控制容器网络的推荐方式,但它确实有些限制。
环境变量注入是静态的,而且容器启动后就不能修改。遗留的--link
参数会和被连接的容器共享所有环境变量,但docker network
命令不同。当你用docker network
把一个容器连到一个网络时,环境变量不能在容器间进行动态共享。
遗留的link
可以给单独的配置了别名的容器提供名字解析。网络限定的别名不能提供这样的隔离,而是把这个别名提供给网络内的所有容器。
下面的例子说明了这种限制。
(译者注:个人觉得下面的例子跟上面的观点没啥关联,要证明上面的观点,可以新建一个容器c7,加到isolated_nw,用–link指定container4的别名c4,然后实验c7能连到c4,但其他容器不能解析c4这个别名)
1.创建另一个容器container6
,连到isolated_nw
,并给它一个别名app
。
$ docker run --network=isolated_nw -itd --name=container6 --network-alias app busybox
8ebe6767c1e0361f27433090060b33200aac054a68476c3be87ef4005eb1df17
2.进入container4
。尝试用容器名container6
和网络别名app
来ping容器。注意解析到的IP是一样的。
$ docker attach container4
/ # ping -w 4 app
PING app (172.25.0.6): 56 data bytes
64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.25.0.6: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.25.0.6: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.25.0.6: seq=3 ttl=64 time=0.097 ms
--- app ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms
/ # ping -w 4 container6
PING container6 (172.25.0.6): 56 data bytes
64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.25.0.6: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.25.0.6: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.25.0.6: seq=3 ttl=64 time=0.097 ms
--- container6 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms

用CTRL-p CTRL-q
来离开container4
并让它保持运行。
3.把container6
连到local_alias
网络,并指定网络内别名scoped-app
。
$ docker network connect --alias scoped-app local_alias container6
现在container6
在网络isolated_nw
内有别名app
,在网络local_alias
内有别名scoped-app
。
4.尝试从container4
(两个网络都有连接)和container5
(只连到了isolated_nw
)中连接这两个别名。
$ docker attach container4
/ # ping -w 4 scoped-app
PING foo (172.26.0.5): 56 data bytes
64 bytes from 172.26.0.5: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.26.0.5: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.26.0.5: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.26.0.5: seq=3 ttl=64 time=0.097 ms
--- foo ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms
用CTRL-p CTRL-q
来离开container4
并让它保持运行。
$ docker attach container5
/ # ping -w 4 scoped-app
ping: bad address 'scoped-app'
用CTRL-p CTRL-q
来离开container5
并让它保持运行。
这表明别名被限定在它所定义的网络内,只有网络内的容器能访问到这个别名。
在一个网络内的多个容器能共享一个网络限定的别名。这提供了一种DNS轮询调度形式的高可用。当使用可能缓存IP地址的软件,如nginx时,这个特性可能不稳定。
下面的例子展示了如何设置并使用网络别名。
注意:使用网络别名来做DNS轮询高可用的场景应该考虑使用集群服务(swarm services)代替。集群服务提供了开箱即用的负载均衡特性。当你连到任一节点,即使是不提供服务的节点时,docker都会把请求发给随机的一个提供服务的节点并管理所有的通信。
1.在网络isolated_nw
中启动container7
并指定和container6
相同的别名app
。
$ docker run --network=isolated_nw -itd --name=container7 --network-alias app busybox
3138c678c123b8799f4c7cc6a0cecc595acbdfa8bf81f621834103cd4f504554
当多个容器共享一个别名时,其中的一个会解析到该别名,如果这个容器挂了,别名会解析到另一个容器,这提供了一种集群内的高可用。
注意:当IP地址被解析到后,被选到的容器是不可预测的。因此,在下面的例子中,在某些步中你可能会得到不同的结果。如果某步的结果返回了container6而你的结果是container7,这就是原因。
2.从container4连续ping别名app
:
$ docker attach container4
$ ping app
PING app (172.25.0.6): 56 data bytes
64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.25.0.6: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.25.0.6: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.25.0.6: seq=3 ttl=64 time=0.097 ms
...
返回的IP是container6
的。
3.在另一个终端,关掉container6
。
$ docker stop container6
再进入container4
的终端,观察结果输出。当container6
停掉后,ping会卡住,因为它是在第一次启动的时候查找IP的,而最初找到的哪个IP已经不可用了。但是ping命令默认有很长的超时时间,所以没有错误输出。
4.用CTRL+c
停掉ping,再次运行ping。
$ ping app
PING app (172.25.0.7): 56 data bytes
64 bytes from 172.25.0.7: seq=0 ttl=64 time=0.095 ms
64 bytes from 172.25.0.7: seq=1 ttl=64 time=0.075 ms
64 bytes from 172.25.0.7: seq=2 ttl=64 time=0.072 ms
64 bytes from 172.25.0.7: seq=3 ttl=64 time=0.101 ms
...
这次解析到了container7
的IP。
5.最后一个测试,重启container6
。
$ docker start container6
在进入container4
的终端,再次运行ping命令。他应该再次解析到container6
。如果你多个重试ping命令,两个容器的IP你应该都能看到。
$ docker attach container4
$ ping app
PING app (172.25.0.6): 56 data bytes
64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.25.0.6: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.25.0.6: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.25.0.6: seq=3 ttl=64 time=0.097 ms
...
用CTRL+C
停掉ping。用CTRL-p CTRL-q
来离开container4
并让它保持运行。
你在任何时间可以把容器从一个网络中断开,通过docker network disconnect
命令。
1.把container2
从isolated_nw
中断开,然后检查container2
和isolated_nw
。
$ docker network disconnect isolated_nw container2
$ docker inspect --format='' container2 | python -m json.tool
{
"bridge": {
"NetworkID":"7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812",
"EndpointID": "9e4575f7f61c0f9d69317b7a4b92eefc133347836dd83ef65deffa16b9985dc0",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:03"
}
}
$ docker network inspect isolated_nw
[
{
"Name": "isolated_nw",
"Id": "06a62f1c73c4e3107c0f555b7a5f163309827bfbbf999840166065a8f35455a8",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.21.0.0/16",
"Gateway": "172.21.0.1/16"
}
]
},
"Containers": {
"467a7863c3f0277ef8e661b38427737f28099b61fa55622d6c30fb288d88c551": {
"Name": "container3",
"EndpointID": "dffc7ec2915af58cc827d995e6ebdc897342be0420123277103c40ae35579103",
"MacAddress": "02:42:ac:19:03:03",
"IPv4Address": "172.25.3.3/16",
"IPv6Address": ""
}
},
"Options": {}
}
]

2.当一个容器从一个网络中断开时,它就不能再和网络中的其他容器通信了,除非他们有其他的公共网络。验证container2
不能在连到isolated_nw
中的container3
。
$ docker attach container2
/ # 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:8 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:648 (648.0 B) 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 container3
PING container3 (172.25.3.3): 56 data bytes
^C
--- container3 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss

3.验证container2
还连在默认的bridge
网络上。
/ # ping container1
PING container1 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.119 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.174 ms
^C
--- container1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.119/0.146/0.174 ms
/ #
4.删掉 container4
, container5
, container6
, 和 container7
.
$ docker stop container4 container5 container6 container7
$ docker rm container4 container5 container6 container7
在某些情况下,比如在多主机网络中不平滑地重启docker守护进程,守护进程不能清除失效的连接终端。这种失效的终端可能导致错误,当一个新容器用和失效的终端一样的名字加入网络时:
ERROR: Cannot start container bc0b19c089978f7845633027aa3435624ca3d12dd4f4f764b61eac4c0610f32e: container already connected to network multihost
要清除这些失效的终端,删掉容器并强制把他们从网络中断开(docker network disconnect -f
)。这样你就能把这些容器连到网络了。
$ docker run -d --name redis_db --network multihost redis
ERROR: Cannot start container bc0b19c089978f7845633027aa3435624ca3d12dd4f4f764b61eac4c0610f32e: container already connected to network multihost
$ docker rm -f redis_db
$ docker network disconnect -f multihost redis_db
$ docker run -d --name redis_db --network multihost redis
7d986da974aeea5e9f7aca7e510bdb216d58682faa83a9040c2f2adc0544795a
当网络内的所有容器都停止或断开后,你就能把网络删除了,如果网络还有连接的终端,删除会报错。
1.把container3
断开isolated_nw
.
$ docker network disconnect isolated_nw container3
2.检查isolated_nw
来验证没有终端连在它上面了。
$ docker network inspect isolated_nw
[
{
"Name": "isolated_nw",
"Id": "06a62f1c73c4e3107c0f555b7a5f163309827bfbbf999840166065a8f35455a8",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.21.0.0/16",
"Gateway": "172.21.0.1/16"
}
]
},
"Containers": {},
"Options": {}
}
]

3.删除isolated_nw
网络。
$ docker network rm isolated_nw
4.列出所有的网络来验证isolated_nw
已经不在了。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
4bb8c9bf4292 bridge bridge local
43575911a2bd host host local
76b7dc932e03 local_alias bridge local
b1a086897963 my-network bridge local
3eb020e70bfd none null local
69568e6336d8 simple-network bridge local
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。