手机版

Docker用户指南(11) – Docker网络命令

时间:2020-03-28 来源:互联网 编辑:宝哥软件园 浏览:

本文介绍与docker网络和在其中的容器的交互的网络子命令示例。这些命令是:

docker network create docker network connect docker network ls docker network rm docker network disconnect docker network inspect

创建网络

当你安装Docker Engine时,它自动创建一个bridge网络。此网络是docker engine依赖的docker0 bridge。除了这个网络,你可以创建自己的bridge或overlay网络。
一个bridge网络存在于运行着docker engine实例的单个主机上。一个overlay网络能跨越运行着它们自己engine的多个主机。如果你执行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/16"
                }
            ]
        },
        "Containers": {},
        "Options": {}
    }
]

不像bridge网络,在创建overlay网络之前需要一些提前存在的条件。这些条件是:

有一个能访问的键值存储。Engine支持Consul, Etcd和ZooKeeper(分布式存储)键值存储。 集群的主机能够访问键值存储。 在集群的每一个主机正确配置Engine daemon。

支持overlay网络的dockerd选项是:

–cluster-store –cluster-store-opt –cluster-advertise

当你创建网络时,Engine默认会为你的网络创建一个不重叠的子网。你可以直接使用–subnet选项来指定一个子网覆盖默认的行为。在一个bridge网络中你只能指定一个子网,而overlay网络支持多个子网。

创建网络时强烈推荐使用–subnet选项。如果–subnet选项没有指定,docker daemon会自动为你的网络选择和分配一个子网,它有可能与另一个不是docker控制的子网重叠。当容器连接到这样的网络时会导致引引连接问题。

除了–subnet选项,你也可以指定–gateway,–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

确保你的子网不会重叠,如果重叠了,网络创建会失败,Engine返回一个错误。
当你创建一个自定义网络时,你可以传递额外的选项到驱动。bridge驱动接受如下选项:

选项 等于 描述 com.docker.network.bridge.name – 创建Linux bridge时使用的bridge名称 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来查看网络,最后附加一个新容器到这个新网络。

$ 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/16"
                }
            ]
        },
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.host_binding_ipv4": "172.23.0.1"
        }
    }
]
 
$ 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网络或自定义插件,从不同主机启动的容器连接到相同的多主机网络也能够也这种方式通信。

基本的容器网络示例

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到上步创建的网络,然后查看这个网络:

$ 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或–ip6参数来分配一个IPv4或IPv6地址给容器。当你以这样的方式在一个使用自定义网络容器中指定一个IP地址时,配置将作为容器配置的一部分保留,并在重新加载容器时应用。当使用非用户定义的网络时,保留分配的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使用的网络资源。

$ 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网络和在第3步连接到了isolated_nw网络。
Docker用户指南(11) – Docker网络命令
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03
eth1 Link encap:Ethernet HWaddr 02:42:AC:15:00:02
7.使用docker attach命令连接到运行中的container2并查看它的网络配置。

$ 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'

不过你仍然可以直接ping ip地址:

/ # 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

9.目前container2附加到了bridge和isolated_nw这两个网络,所以你能与container1和container3两个通信。不过container3和container1没有在任何一个共同的网络,所以它们无法通信。要验证这个,可以attach到container3并尝试ping container1的ip地址。

$ 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

链接(linking)不使用自定义网络的容器

当你完成了上面的步骤后,container2能自动地解析container3的名称,是因为两个容器都连接到了isolated_nw网络。不过连接到默认bridge网络的容器无法解析彼此的容器名称。如果你需要在默认的bridge网络能够解析彼此的容器名称,你需要使用旧的链接(legacy link)功能。这是使用–link唯一推荐的一个用例。你应该考虑使用自定义网络替代。
使用旧的link参数对在默认bridge网络的通信增加了如下功能:

解析容器名称为IP地址 使用-link=CONTAINER-NAME:ALIAS定义一个网络别名作为引用链接的容器的另一个方式 安全容器连接 环境变量注入

重申一下,当你使用一个自定义的网络时,下面的所有功能不需要额外的配置默认提供。此外,你能够动态地附加到多个网络和从多个网络脱离。

使用DNS自动名称解析 支持使用–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地址。

注意:使用旧的链接创建的容器之间的任意链接是静态并且硬绑定容器的别名。它不允许链接的容器重启。在自定义网络的链接功能支持容器之间动态链接并允许重启和链接的容器ip地址更改。

因为你没有创建容器container5,所以尝试ping它的话会返回错误。附加到container4并尝试ping container5或c5:

$ docker attach container4
 
$ ping container5
 
ping: bad address 'container5'
 
$ ping c5
 
ping: bad address 'c5'

2.创建另一个容器container5,并链接它到使用c4别名的container4.

$ docker run --network=isolated_nw -itd --name=container5 --link container4:c4 busybox
 
72eccf2208336f31e9e33ba327734125af00d1e1d2657878e2ee8154fbb23c7a

现在附着到container4并尝试ping c5和container5。

$ 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

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

网络别名作用域示例

当你链接容器,不论使用的是旧的link方式或者使用自定义网络,你指定的任何别名只对链接的容器有效,不会对在默认bridge网络的其它容器有用。
此外,如果一个容器属于多个网络,一个给定的链接别名的作用域是一个给定的网络。因此一个容器在不同的网络能被链接到不同的别名,且不在同一个网络的容器别名不会有效。
下面的示例说明了这些点。
1.创建另一个网络local_alias

$ docker network create -d bridge --subnet 172.26.0.0/24 local_alias
76b7dc932e037589e6553f59f76008e5b76fa069638cd39776b890607f567aaa

2.下一步连接container4和container5到一个新的带有别名foo和bar的网络local_alias:

$ docker network connect --link container5:foo local_alias container4
$ docker network connect --link container4:bar local_alias container5

3.附着container4并尝试ping container4的别名foo,然后尝试ping container5的别名c5:

$ 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都成功了,不过子网不同,意味着网络不一样。
4.从isolated_nw网络断开container5的连接。附着container4并尝试ping c5和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的别名c5到达此容器,不过你仍然能够使用别名foo到达container4。

docker网络的限制

虽然docker network命令是控制你的容器使用的网络的推荐方法,不过它有一些限制。

环境变量注入

环境变量本质上是静态的并且容器启动之后不再能更改环境变量。旧的–link参数共享所有的环境变量给链接的容器,不过docker network命令没有等同的设置。当你使用docker network连接到一个网络,容器之间的环境变量无法动态的存在。

理解网络范围的别名

旧的link提供了在配置别名的容器隔离的名称解析。网络范围的别名不允许这种方式的隔离,但是此别名在网络中的所有成员可用。
下面的示例说明了这些限制。
1.创建另一个容器container6,指定网络为isolated_nw,网络别名为app。

$ docker run --network=isolated_nw -itd --name=container6 --network-alias app busybox
 
8ebe6767c1e0361f27433090060b33200aac054a68476c3be87ef4005eb1df17

2.附着到container4。尝试ping container6和网络别名app。注意这两个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 container5 (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

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网络)ping这些别名。

$ 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

再附着到container5。

$ docker attach container5
 
/ # ping -w 4 scoped-app
ping: bad address 'scoped-app'

这说明了别名的作用域是在它指定的网络并且只有连接到这个网络的容器才能够访问这些别名。

将多个容器解析到同一个别名

在同一个网络中多个容器可以共享同一个网络范围别名(network-scoped alias)。下面的示例解释是如何工作的。
1.启动container7,在isolated_nw网络中设置一个与container6同样的别名app。

$ docker run --network=isolated_nw -itd --name=container7 --network-alias app busybox
 
3138c678c123b8799f4c7cc6a0cecc595acbdfa8bf81f621834103cd4f504554

当多个容器共享同一个别名时,这个别名将解析到这些容器的其中一个。如果那个容器不可用,别名将解析到另一个可用的。这在集群中提供了一种高可用的方法。

当别名解析出多个ip时,容器将随机的选择一个。由于这个原因,下面的示例的结果可能与你的不一样。

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
...

目前解析到了container6。
3.在另一个终端,停止container6。

$ docker stop container6

然后附着到container4观察ping的输出,当container4停机时ping会停止。
4.退出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
...

现在app别名解析到了container7的ip地址。
5.最后一次测试,重启container6。

$ docker start container6

在终端中附着container4,再次执行ping命令。它可能会再次解析到container6。如果你多次启动和停止ping命令,你会发现有时解析到container6,有时是container7。

$ 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
...

断开容器网络

你可以在任何时候使用docker network disconnect命令从一个网络断开容器。
1.从isolated_nw网络断开container2,然后查看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.当一个容器从一个网络断开,它就不再能够与其它连接到这个网络的容器通信,除非它还有与这些容器相同的网络。验证一下在isolated_nw网络中,container2不再能够达到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
/ #

处理过时的网络endpoints

在一些场景中,如docker daemon在多主机网络意外的重启,daemon无法清理过时的连接endpoint。当一个新的容器连接到与过时endpoint有相同名称的网络时会导致错误。

ERROR: Cannot start container bc0b19c089978f7845633027aa3435624ca3d12dd4f4f764b61eac4c0610f32e: container already connected to network multihost

要清理这些过时的endpoints,先删除容器再强制地从网络断开它。

$ 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.从isolated_nw断开container3。

$ 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

版权声明:Docker用户指南(11) – Docker网络命令是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。

相关文章推荐