Docker容器和服务如此强大的缘由之一是您能够将它们链接在一块儿,或将它们链接到非Docker工做负载。 Docker容器和服务甚至不须要知道它们已部署在Docker上,也没必要知道它们的对等对象是否也是Docker工做负载。 不管您的Docker主机运行Linux,Windows仍是二者结合,您均可以使用Docker以与平台无关的方式管理它们。node
本主题定义了一些基本的Docker网络概念,并帮助您设计和部署应用程序以充分利用这些功能。nginx
Docker的网络子系统使用驱动程序是可插拔的。默认状况下存在几个驱动程序,并提供核心网络功能:docker
bridge
:默认的网络驱动程序。 若是您未指定驱动程序,则这是您正在建立的网络类型。当您的应用程序在须要通讯的独立容器中运行时,一般会使用网桥网络。host
:对于独立容器,去掉容器和Docker主机之间的网络隔离,直接使用主机的网络。host
仅可用于Docker 17.06及更高版本上的集群服务。overlay
:overlay
网络将多个Docker守护程序链接在一块儿,并使群集服务可以相互通讯。您还可使用overlay
网络来促进群集服务和独立容器之间或不一样Docker守护程序上的两个独立容器之间的通讯。这种策略消除了在这些容器之间进行操做系统级路由的须要macvlan
:Macvlan网络容许您将MAC地址分配给容器,使其在网络上显示为物理设备。 Docker守护程序经过其MAC地址将流量路由到容器。 在处理但愿直接链接到物理网络而不是经过Docker主机的网络堆栈进行路由的传统应用程序时,使用macvlan驱动程序有时是最佳选择。none
:对于此容器,禁用全部联网。 一般与自定义网络驱动程序一块儿使用。none
不适用于swarm services.这一部分包含三个不一样的指南,你能够在不一样系统上运行他们,可是对于最后两个,你须要额外的Docker主机运行。shell
尽管overlay网络一般用于集群服务,但Docker 17.06及更高版本容许您将overlay网络用于独立容器。 这是使用overlay网络的教程的一部分。安全
在此示例中,您在同一Docker主机上启动了两个不一样的alpine容器,并进行了一些测试以了解它们如何相互通讯。 您须要安装并运行Docker。bash
1.打开一个终端窗口。 在执行其余任何操做以前,请先列出当前网络。 若是您从未在此Docker守护程序上添加网络或初始化群组,则应该看到如下内容。 您可能会看到不一样的网络,但至少应该看到如下内容(网络ID会有所不一样):网络
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
17e324f45964 bridge bridge local
6ed54d316334 host host local
7092879f2cc8 none null local
复制代码
列出了默认的桥接网络,以及host
和none
。 后两个不是彻底成熟的网络,但用于启动直接链接到Docker守护程序主机的网络堆栈的容器,或用于启动不包含网络设备的容器。 本教程将把两个容器链接到桥接网络。oop
2.开启两个alpine
容器运行ash
,它是Alpine默认的shell,而不是bash
. -dit
标志的意思是启动分离的容器(在后台),交互的(具备键入的能力)和TTY(以便您能够看到输入和输出)。因为您是分开启动的,所以您不会当即链接到该容器。而是将打印容器的ID。 由于你未指定任何--network
选项,因此容器将链接到默认的网桥网络。测试
$ docker run -dit --name alpine1 alpine ash
$ docker run -dit --name alpine2 alpine ash
复制代码
检查两个容器是否确实已启动:ui
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
602dbf1edc81 alpine "ash" 4 seconds ago Up 3 seconds alpine2
da33b7aa74b0 alpine "ash" 17 seconds ago Up 16 seconds alpine1
复制代码
3.检查网桥网络以查看链接了哪些容器。
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "17e324f459648a9baaea32b248d3884da102dde19396c25b30ec800068ce6b10",
"Created": "2017-06-22T20:27:43.826654485Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Containers": {
"602dbf1edc81813304b6cf0a647e65333dc6fe6ee6ed572dc0f686a3307c6a2c": {
"Name": "alpine2",
"EndpointID": "03b6aafb7ca4d7e531e292901b43719c0e34cc7eef565b38a6bf84acf50f38cd",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"da33b7aa74b0bf3bda3ebd502d404320ca112a268aafe05b4851d1e3312ed168": {
"Name": "alpine1",
"EndpointID": "46c044a645d6afc42ddd7857d19e9dcfb89ad790afb5c239a35ac0af5e8a5bc5",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/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": "1500"
},
"Labels": {}
}
]
复制代码
在顶部附近,列出了有关桥接网络的信息,包括Docker主机和桥接网络之间的网关的IP地址(172.17.0.1
)。 在Containers
项下,列出了每一个链接的容器及其IP地址信息(lpine1
为172.17.0.2
,alpine2
为172.17.0.3
)
4.容器在后台运行。 使用docker attach
命令链接到alpine1
。
$ docker attach alpine1
/ #
复制代码
提示符将更改成#
以指示您是容器中的root
用户。 使用ip addr show
命令从容器中查看alpine1
的网络接口:
# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
27: eth0@if28: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:2/64 scope link
valid_lft forever preferred_lft forever
复制代码
第一个接口是环回设备。如今先忽略它。注意,第二个接口的IP地址是172.17.0.2
,这与前面步骤中显示的alpine1
的地址相同。
5.在alpine1
内部,经过ping baidu.com
确保您能够链接到互联网。 -c 2
标志将命令限制为两ping
尝试。
➜ ~ ping -c 2 baidu.com
PING baidu.com (39.156.69.79): 56 data bytes
64 bytes from 39.156.69.79: icmp_seq=0 ttl=46 time=34.887 ms
64 bytes from 39.156.69.79: icmp_seq=1 ttl=46 time=41.880 ms
--- baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 34.887/38.383/41.880/3.497 ms
➜ ~
复制代码
6.如今尝试ping
第二个容器。 首先,经过其IP地址172.17.0.3
对其执行ping
操做:
# ping -c 2 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.086 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.094 ms
--- 172.17.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.086/0.090/0.094 ms
复制代码
这样成功了。 接下来,尝试按容器名称ping alpine2
容器。 这将失败。
# ping -c 2 alpine2
ping: bad address 'alpine2'
复制代码
7.经过使用分离序列CTRL
+ p
CTRL
+ q
(按住CTRL
并键入p
后跟q
)从alpine1
分离而不中止它。 若是愿意,请附加到alpine2
并在那里重复步骤四、5和6,将alpine1
代替为alpine2
。
8.中止并删除两个容器。
$ docker container stop alpine1 alpine2
$ docker container rm alpine1 alpine2
复制代码
请记住,不建议将默认网桥网络用于生产。
In this example, we again start two alpine containers, but attach them to a user-defined network called alpine-net which we have already created. These containers are not connected to the default bridge network at all. We then start a third alpine container which is connected to the bridge network but not connected to alpine-net, and a fourth alpine container which is connected to both networks. 在此示例中,咱们再次启动两个Alpine
容器,可是将它们附加到咱们已经建立的名为alpine-net
的用户定义网络上。 这些容器根本没有链接到默认桥接网络。 而后,咱们启动链接到默认网桥网络但未链接alpine-net
的第三个alpine
容器,以及链接到两个网络的第四个alpine
容器。
1.建立 alpine-net
网络. 你不须要指定--driver bridge
标签由于它是默认的,但本实例展现了如何指定它:
$ docker network create --driver bridge alpine-net
复制代码
2.列出Docker网络
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
e9261a8c9a19 alpine-net bridge local
17e324f45964 bridge bridge local
6ed54d316334 host host local
7092879f2cc8 none null local
复制代码
检查alpine-net网络。这显示了它的IP地址,以及没有容器链接到它的事实.
$ docker network inspect alpine-net
[
{
"Name": "alpine-net",
"Id": "e9261a8c9a19eabf2bf1488bf5f208b99b1608f330cff585c273d39481c9b0ec",
"Created": "2017-09-25T21:38:12.620046142Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
复制代码
请注意,该网络的网关是172.18.0.1
,而默认网桥网络的网关是172.17.0.1
。 您系统上的确切IP地址可能不一样。
3.建立你的第四个容器,注意--network
选项。在docker run
命令中你只能链接到一个网络。因此,你须要使用docker network connect
命令将第四个容器链接到默认桥接网络上。
$ docker run -dit --name alpine1 --network alpine-net alpine ash
$ docker run -dit --name alpine2 --network alpine-net alpine ash
$ docker run -dit --name alpine3 alpine ash
$ docker run -dit --name alpine4 --network alpine-net alpine ash
$ docker network connect bridge alpine4
复制代码
验证全部容器都在运行:
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
156849ccd902 alpine "ash" 41 seconds ago Up 41 seconds alpine4
fa1340b8d83e alpine "ash" 51 seconds ago Up 51 seconds alpine3
a535d969081e alpine "ash" About a minute ago Up About a minute alpine2
0a02c449a6e9 alpine "ash" About a minute ago Up About a minute alpine1
复制代码
4.再次检查默认网桥网络和alpine-net
网:
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "17e324f459648a9baaea32b248d3884da102dde19396c25b30ec800068ce6b10",
"Created": "2017-06-22T20:27:43.826654485Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Containers": {
"156849ccd902b812b7d17f05d2d81532ccebe5bf788c9a79de63e12bb92fc621": {
"Name": "alpine4",
"EndpointID": "7277c5183f0da5148b33d05f329371fce7befc5282d2619cfb23690b2adf467d",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"fa1340b8d83eef5497166951184ad3691eb48678a3664608ec448a687b047c53": {
"Name": "alpine3",
"EndpointID": "5ae767367dcbebc712c02d49556285e888819d4da6b69d88cd1b0d52a83af95f",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/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": "1500"
},
"Labels": {}
}
]
复制代码
alpine3
和 alpine4
容器链接到了默认的桥接网络
$ docker network inspect alpine-net
[
{
"Name": "alpine-net",
"Id": "e9261a8c9a19eabf2bf1488bf5f208b99b1608f330cff585c273d39481c9b0ec",
"Created": "2017-09-25T21:38:12.620046142Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Containers": {
"0a02c449a6e9a15113c51ab2681d72749548fb9f78fae4493e3b2e4e74199c4a": {
"Name": "alpine1",
"EndpointID": "c83621678eff9628f4e2d52baf82c49f974c36c05cba152db4c131e8e7a64673",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"156849ccd902b812b7d17f05d2d81532ccebe5bf788c9a79de63e12bb92fc621": {
"Name": "alpine4",
"EndpointID": "058bc6a5e9272b532ef9a6ea6d7f3db4c37527ae2625d1cd1421580fd0731954",
"MacAddress": "02:42:ac:12:00:04",
"IPv4Address": "172.18.0.4/16",
"IPv6Address": ""
},
"a535d969081e003a149be8917631215616d9401edcb4d35d53f00e75ea1db653": {
"Name": "alpine2",
"EndpointID": "198f3141ccf2e7dba67bce358d7b71a07c5488e3867d8b7ad55a4c695ebb8740",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
复制代码
alpine1
, alpine2
, 和 alpine4
容器链接到了alpine-net
网络.
5。在像alpine-net
这样的用户定义网络上,容器不只能够按IP地址进行通讯,并且还能够将容器名称解析为IP地址。 此功能称为自动服务发现。 让咱们链接到alpine1
并进行测试。 alpine1
应该可以将alpine2
和alpine4
(以及alpine1
自己)解析为IP地址。
$ docker container attach alpine1
# ping -c 2 alpine2
PING alpine2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.085 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.090 ms
--- alpine2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.085/0.087/0.090 ms
# ping -c 2 alpine4
PING alpine4 (172.18.0.4): 56 data bytes
64 bytes from 172.18.0.4: seq=0 ttl=64 time=0.076 ms
64 bytes from 172.18.0.4: seq=1 ttl=64 time=0.091 ms
--- alpine4 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.076/0.083/0.091 ms
# ping -c 2 alpine1
PING alpine1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.026 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.054 ms
--- alpine1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.026/0.040/0.054 ms
复制代码
6.从 alpine1
, 你没法链接到alpine3
, 由于它不在alpine-net
网内.
# ping -c 2 alpine3
ping: bad address 'alpine3'
复制代码
不只如此,你也不能经过它的IP地址从alpine1
链接到alpine3
。查看docker network inspect
的输出,找到alpine3
的IP地址:172.17.0.2
,试着ping它。
# ping -c 2 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
复制代码
使用分离序列CTRL
+ p
CTRL
+ q
(按住CTRL
并键入p
后跟q
)从alpine1
分离。
7.请记住,alpine4
已链接到默认网桥网络和alpine-net
。 它应该可以到达全部其余容器。 可是,您将须要按其IP地址寻址alpine3
。 附加到它并运行测试。
$ docker container attach alpine4
# ping -c 2 alpine1
PING alpine1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.074 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.082 ms
--- alpine1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.074/0.078/0.082 ms
# ping -c 2 alpine2
PING alpine2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.075 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.080 ms
--- alpine2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.075/0.077/0.080 ms
# ping -c 2 alpine3
ping: bad address 'alpine3'
# ping -c 2 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.089 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.075 ms
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.075/0.082/0.089 ms
# ping -c 2 alpine4
PING alpine4 (172.18.0.4): 56 data bytes
64 bytes from 172.18.0.4: seq=0 ttl=64 time=0.033 ms
64 bytes from 172.18.0.4: seq=1 ttl=64 time=0.064 ms
--- alpine4 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.033/0.048/0.064 ms
复制代码
8.做为最后一个测试,经过ping www.baidu.com
确保全部的容器均可以链接到网络.由于当前你已经链接到了alpine4
,就从它开始,而后退出alpine4
并链接到alpine3
(该容器仅仅链接到默认的桥接网络) 进行重试。最后链接到alpine1
(它仅仅链接到alpine-net
网络)并进行重试.
# ping -c 2 baidu.com
PING baidu.com (172.217.3.174): 56 data bytes
64 bytes from 172.217.3.174: seq=0 ttl=41 time=9.778 ms
64 bytes from 172.217.3.174: seq=1 ttl=41 time=9.634 ms
--- baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 9.634/9.706/9.778 ms
CTRL+p CTRL+q
$ docker container attach alpine3
# ping -c 2 baidu.com
PING baidu.com (172.217.3.174): 56 data bytes
64 bytes from 172.217.3.174: seq=0 ttl=41 time=9.706 ms
64 bytes from 172.217.3.174: seq=1 ttl=41 time=9.851 ms
--- baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 9.706/9.778/9.851 ms
CTRL+p CTRL+q
$ docker container attach alpine1
# ping -c 2 baidu.com
PING baidu.com (172.217.3.174): 56 data bytes
64 bytes from 172.217.3.174: seq=0 ttl=41 time=9.606 ms
64 bytes from 172.217.3.174: seq=1 ttl=41 time=9.603 ms
--- baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 9.603/9.604/9.606 ms
CTRL+p CTRL+q
复制代码
9.最后中止并删除全部容器并删除alpine-net
网络
$ docker container stop alpine1 alpine2 alpine3 alpine4
$ docker container rm alpine1 alpine2 alpine3 alpine4
$ docker network rm alpine-net
复制代码
本系列教程讨论集群服务的网络。本主题包含四个部份内容,你能够在不一样的平台上运行他们,可是对于最后两个,你须要一个额外的Docker主机。
overlay network
演示了如何在初始化或加入群集时使用Docker自动为您设置的默认的overlay network
。 该网络不是生产系统的最佳选择。overlay network
显示了如何建立和使用本身的自定义overlay network
来链接服务。 建议将其用于生产中运行的服务。overlay network
用于独立容器显示了如何使用overlay network
在不一样Docker守护程序上的独立容器之间进行通讯。overlay network
在独立容器与群集服务之间创建通讯。 Docker 17.06及更高版本支持此功能。这些要求您至少有一个单节点群集,这意味着您已启动Docker并在主机上运行docker swarm init
。 您也能够在多节点集群上运行示例。 最后一个示例须要Docker 17.06或更高版本。
在本例中,您启动一个alpine
服务,并从各个服务容器的角度分析网络的特征。
本教程不讨论有关如何实现overlay network的特定于操做系统的详细信息,而是重点关注从服务的角度来看,overlay network是如何工做的。
本教程须要三台物理或虚拟Docker主机,它们能够相互通讯,而且都运行Docker 17.03或更高版本的新安装。 本教程假定这三台主机在同一网络上运行,而且不涉及防火墙。
这些主机将被称为manager
, worker-1
,worker-2
.manager
主机即做为管理者又做为工做者,这意味着它既要运行服务任务,也要管理swarm. worker-1
和 worker-2
将仅做为工做者。
若是您没有三台主机,一个简单的解决方案是在云提供商(例如Amazon EC2)上设置三台Ubuntu主机,它们所有位于同一网络上,并容许与该网络上的全部主机进行全部通讯(使用诸如 EC2安全组),而后按照Ubuntu上Docker Engine-Community的安装说明进行操做。
在此过程结束时,全部三个Docker主机都将加入集群,并使用称为ingress
的覆盖网络链接在一块儿.
1.在manager
上,初始化swarm
集群。若是主机只有一个网络接口,--advertise-addr
选项是可选的。
$ docker swarm init --advertise-addr=<IP-ADDRESS-OF-MANAGER>
复制代码
记下所打印的文本,由于其中包含将用于将worker-1和worker-2加入到群中的令牌。 将令牌存储在密码管理器中是一个好主意。
2.在worker-1
上,加入到swarm
。若是主机只有一个网络接口,--advertise-addr
选项是可选的.
$ docker swarm join --token <TOKEN> \
--advertise-addr <IP-ADDRESS-OF-WORKER-1> \
<IP-ADDRESS-OF-MANAGER>:2377
复制代码
3.在worker-2
上,加入到swarm
。若是主机只有一个网络接口,--advertise-addr
选项是可选的.
$ docker swarm join --token <TOKEN> \
--advertise-addr <IP-ADDRESS-OF-WORKER-2> \
<IP-ADDRESS-OF-MANAGER>:2377
复制代码
4.在manager
上, 列出全部的节点。这个命令只能在manager上执行。
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
d68ace5iraw6whp7llvgjpu48 * ip-172-31-34-146 Ready Active Leader
nvp5rwavvb8lhdggo8fcf7plg ip-172-31-35-151 Ready Active
ouvx2l7qfcxisoyms8mtkgahw ip-172-31-36-89 Ready Active
复制代码
您也可使用--filter
标志按角色进行过滤:
$ docker node ls --filter role=manager
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
d68ace5iraw6whp7llvgjpu48 * ip-172-31-34-146 Ready Active Leader
$ docker node ls --filter role=worker
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
nvp5rwavvb8lhdggo8fcf7plg ip-172-31-35-151 Ready Active
ouvx2l7qfcxisoyms8mtkgahw ip-172-31-36-89 Ready Active
复制代码
5.列出manager
,worker-1
,worker-2
上全部的网络,请注意它们如今都有一个叫作ingress
的覆盖网络和一个叫docker_gwbridge
的桥接网络。这里只展现manager的:
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
495c570066be bridge bridge local
961c6cae9945 docker_gwbridge bridge local
ff35ceda3643 host host local
trtnl4tqnc3n ingress overlay swarm
c8357deec9cb none null local
复制代码
docker_gwbridge
将ingress
网络链接到Docker主机的网络接口,以便流量能够往返于群管理者和工做者。若是建立群集服务但未指定网络,则它们将链接到ingress
网络.建议对将一块儿使用的每一个应用程序或一组应用程序使用单独的覆盖网络。在下一个过程当中,您将建立两个覆盖网络并将服务链接到每一个覆盖网络。
1.在manager
上,建立一个新的overlay network叫nginx-net
:
$ docker network create -d overlay nginx-net
复制代码
您无需在其余节点上建立overlay网络,由于当其中一个节点开始运行须要该overlay网络的服务任务时,overlay网络会自动建立。
2.在manager
上, 建立一个有5个副本的Nginx服务并链接到nginx-net
.服务将对外开放80端口。全部服务任务容器均可以在不打开任何端口的状况下彼此通讯。
服务只能在管理器上建立
$ docker service create \
--name my-nginx \
--publish target=80,published=80 \
--replicas=5 \
--network nginx-net \
nginx
复制代码
ingress
的默认发布模式, 在你没有为--publish
选项指定一个mode
时使用。这意味着你若是访问manager
,worker-1
或者worker-2
上的80端口,你将链接到5个服务任务中的任何一个的80端口上。即使当前并无任务运行在你访问的节点上。若是你想使用host
模式发布端口,你能够在--publish
选项上增长mode=host
。可是,这种状况下,你要用--mode global
代替 --replicas=5
, 由于只有一个服务任务能够绑定到给定节点上的给定端口。
3.运行docker service ls
监视服务启动进度,这可能须要几秒钟。
4.在manage
,worker-1
,worker-2
上检查nginx-net
网络. 记住你不须要在worker-1
和worker-2
上手动建立它,由于Docker会给你建立好。输出会很长,可是只需注意Containers
和Peers
部分。Containers
列出了全部的从该主机链接到overlay网络的服务任务(或者单独的容器)。
5.对于manager
,使用docker service inspect my-nginx
检查服务,并注意有关服务使用的端口和端点的信息。
6.建立一个新的网络nginx-net-2
, 而后使用这个新的网络更新服务:
$ docker network create -d overlay nginx-net-2
复制代码
$ docker service update \
--network-add nginx-net-2 \
--network-rm nginx-net \
my-nginx
复制代码
7.运行docker service ls
检查服务已经更新了,而且全部的任务已经从新部署。运行 docker network inspect nginx-net
验证没有容器链接到它。对nginx-net-2
运行相同的命令,注意全部的服务任务容器都链接到它。
overlay网络在swarn工做节点上是按需自动建立的,他们不会自动删除
8.清理服务和网络。 在管理器中,运行如下命令。 管理者将指示工做人员自动删除网络。
$ docker service rm my-nginx
$ docker network rm nginx-net nginx-net-2
复制代码
本教程假设群集已经设置好,而且您是在一个管理器上。
1.建立用户定义的覆盖网络。
$ docker network create -d overlay my-overlay
复制代码
2.使用overlay网络启动一个服务并将端口80发布到Docker主机上的8080上
$ docker service create \
--name my-nginx \
--network my-overlay \
--replicas 1 \
--publish published=8080,target=80 \
nginx:latest
复制代码
3.运行docker network inspect my-overlay
验证my-nginx
服务任务已经链接到它了。经过查看Containers
部分。
4.删除服务和网络
$ docker service rm my-nginx
$ docker network rm my-overlay
复制代码
此示例演示了DNS容器发现-具体地说,是如何使用覆盖网络在不一样Docker守护程序上的独立容器之间进行通讯。 步骤以下:
host1
上, 初始化节点为一个swarm(manager).host2
上, 加入该节点到swarm中(做为工做节点)host1
上,建立一个可链接的覆盖网络(test-net
)。host1
上,在test-net
上运行一个交互式alpine
容器 (alpine1
)。host2
上,在test-net
上运行一个交互式,可分离的alpine
容器 (alpine2
)。host1
上, 从一个alpine1
会话中,ping alpine2
对于此测试,您须要两个能够相互通讯的不一样Docker主机。 每一个主机必须具备Docker 17.06或更高版本,而且在两个Docker主机之间打开如下端口:
一种简单的设置方法是拥有两个VM(本地或在AWS等云提供商上),每一个VM均已安装并正在运行Docker。 若是您使用的是AWS或相似的云计算平台,最简单的配置是使用一个安全组,该安全组打开两个主机之间的全部传入端口以及来自客户端IP地址的SSH端口。
此示例将咱们群中的两个节点称为host1
和host2
。 此示例还使用Linux主机,可是相同的命令在Windows上也可使用。
1.设置swarm 在host1
上,初始化集群(若是出现提示,请使用--advertise-addr
指定与集群中其余主机通讯的接口的IP地址,例如AWS上的私有IP地址):
$ docker swarm init
Swarm initialized: current node (vz1mm9am11qcmo979tlrlox42) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-5g90q48weqrtqryq4kj6ow0e8xm9wmv9o6vgqc5j320ymybd5c-8ex8j0bc40s6hgvy5ui5gl4gy 172.31.47.252:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
复制代码
在host2
上,按照上述说明加入群集:
$ docker swarm join --token <your_token> <your_ip_address>:2377
This node joined a swarm as a worker.
复制代码
若是节点没法加入群集,则docker swarm join
命令会超时。 要解决此问题,请在host2
上运行docker swarm leave --force
,验证您的网络和防火墙设置,而后重试。
2.在host1
上, 建立一个能够链接的overlay网络叫test-net
:
$ docker network create --driver=overlay --attachable test-net
uqsof8phj3ak0rq9k86zta6ht
复制代码
注意返回的NETWORK ID-从host2链接到它时,您将再次看到它。
3.在host1
上,启动一个交互式的容器alpine1
链接到test-net
:
$ docker run -it --name alpine1 --network test-net alpine
/ #
复制代码
4.在host2
上, 罗列出可用的网络--注意test-net
还不存在:
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
ec299350b504 bridge bridge local
66e77d0d0e9a docker_gwbridge bridge local
9f6ae26ccb82 host host local
omvdxqrda80z ingress overlay swarm
b65c952a4b2b none null local
复制代码
5.On host2
, 以-d
和 (-it
) 的方式启动一个容器 (alpine2
) 并链接到test-net
:
$ docker run -dit --name alpine2 --network test-net alpine
fb635f5ece59563e7b8b99556f816d24e6949a5f6a5b1fbd92ca244db17a4342
复制代码
自动DNS容器发现仅适用于惟一的容器名称。
6.在host2
上, 验证 test-net
网络已经建立(和host1
上的test-net
有同样的NETWORK ID):
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
...
uqsof8phj3ak test-net overlay swarm
复制代码
7.在host1
上, 在alpine1
的交互终端内ping alpine2
:
/ # ping -c 2 alpine2
PING alpine2 (10.0.0.5): 56 data bytes
64 bytes from 10.0.0.5: seq=0 ttl=64 time=0.600 ms
64 bytes from 10.0.0.5: seq=1 ttl=64 time=0.555 ms
--- alpine2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.555/0.577/0.600 ms
复制代码
两个容器与链接两个主机的覆盖网络通讯。若是你在host2
主机上运行另外一个alpine容器,而不detached.你能够从host2
ping alpine1
(这里咱们增长了容器自动清理的选项):
$ docker run -it --rm --name alpine3 --network test-net alpine
/ # ping -c 2 alpine1
/ # exit
复制代码
8.在host1
上, 关闭alpine1
的会话 (这将中止容器):
/ # exit
复制代码
9.清理你的容器和网络 您必须在每一个主机上独立中止和删除容器,由于Docker守护程序是独立运行的,而且它们是独立的容器。 您只须要删除host1
上的网络,由于当您中止host2
上的alpine2
时,test-net
就会消失。
在host2
上,中止alpine2
,检查test-net
已经删除,而后删除alpine2
:
$ docker container stop alpine2
$ docker network ls
$ docker container rm alpine2
复制代码
在 host1
上, 删除 alpine1
and test-net
:
$ docker container rm alpine1
$ docker network rm test-net
复制代码
本例须要Docker 17.06或更高版本。
在此示例中,您在同一Docker主机上启动了两个不一样的alpine1
容器,并进行了一些测试以了解它们如何相互通讯。 您须要安装并运行Docker。
1.打开一个终端窗口。 在执行其余任何操做以前,请先列出当前网络。 若是您从未在此Docker守护程序上添加网络或初始化群组,则应该看到如下内容。 您可能会看到不一样的网络,但至少应该看到如下内容(网络ID会有所不一样):
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
17e324f45964 bridge bridge local
6ed54d316334 host host local
7092879f2cc8 none null local
复制代码
列出了默认的桥接网络,以及host
和none
。 后两个不是彻底成熟的网络,但用于启动直接链接到Docker守护程序主机的网络堆栈的容器,或用于启动不包含网络设备的容器。 本教程将把两个容器链接到桥接网络。
2.启动两个运行ash
的Alpine容器,这是Alpine的默认shell,而不是bash
。 -dit
标志的意思是启动分离的容器(在后台),交互的(具备键入的能力)和TTY(以便您能够看到输入和输出)。 因为您是分开启动的,所以您不会当即链接到该容器。 而是将打印容器的ID。 由于您未指定任何--network
标志,因此容器将链接到默认的网桥网络。
$ docker run -dit --name alpine1 alpine ash
$ docker run -dit --name alpine2 alpine ash
复制代码
检查两个容器是否确实已启动:
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
602dbf1edc81 alpine "ash" 4 seconds ago Up 3 seconds alpine2
da33b7aa74b0 alpine "ash" 17 seconds ago Up 16 seconds alpine1
复制代码
3.检查网桥网络以查看链接了哪些容器。
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "17e324f459648a9baaea32b248d3884da102dde19396c25b30ec800068ce6b10",
"Created": "2017-06-22T20:27:43.826654485Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Containers": {
"602dbf1edc81813304b6cf0a647e65333dc6fe6ee6ed572dc0f686a3307c6a2c": {
"Name": "alpine2",
"EndpointID": "03b6aafb7ca4d7e531e292901b43719c0e34cc7eef565b38a6bf84acf50f38cd",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"da33b7aa74b0bf3bda3ebd502d404320ca112a268aafe05b4851d1e3312ed168": {
"Name": "alpine1",
"EndpointID": "46c044a645d6afc42ddd7857d19e9dcfb89ad790afb5c239a35ac0af5e8a5bc5",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/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": "1500"
},
"Labels": {}
}
]
复制代码
在顶部附近,列出了有关桥接网络的信息,包括Docker主机和桥接网络之间的网关的IP地址(172.17.0.1
)。 在Containers
项下,列出了每一个链接的容器及其IP地址信息(alpine1
为172.17.0.2
,alpine2
为172.17.0.3
)。
4.容器在后台运行。 使用docker attach
命令链接到alpine1
。
$ docker attach alpine1
/ #
复制代码
提示符将更改成#
以指示您是容器中的root
用户。 使用ip addr show
命令从容器中查看alpine1
的网络接口:
# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
27: eth0@if28: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:2/64 scope link
valid_lft forever preferred_lft forever
复制代码
第一个接口是环回设备。如今先忽略它。注意,第二个接口的IP地址是172.17.0.2
,这与前面步骤中显示的alpine1
的地址相同。
5.在alpine1
内部,经过ping baidu.com
确保您能够链接到互联网。-c 2
标志将命令限制两次两次ping操做。
# ping -c 2 baidu.com
PING baidu.com (172.217.3.174): 56 data bytes
64 bytes from 172.217.3.174: seq=0 ttl=41 time=9.841 ms
64 bytes from 172.217.3.174: seq=1 ttl=41 time=9.897 ms
--- baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 9.841/9.869/9.897 ms
复制代码
7.如今尝试ping第二个容器。 首先,经过其IP地址172.17.0.3
对其执行ping操做:
# ping -c 2 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.086 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.094 ms
--- 172.17.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.086/0.090/0.094 ms
复制代码
这样成功了。 接下来,尝试按容器名称ping alpine2
容器。 这将失败。
# ping -c 2 alpine2
ping: bad address 'alpine2'
复制代码
7.经过使用分离序列CTRL
+ p
CTRL
+ q
(按住CTRL
并键入p
后跟q
)从alpine1
分离而不中止它。 若是愿意,请附加到alpine2
并在那里重复步骤四、5和6,将alpine1
代替为alpine2
。
8.中止并删除容器;
$ docker container stop alpine1 alpine2
$ docker container rm alpine1 alpine2
复制代码
请记住,不建议将默认网桥网络用于生产。