与独立容器联网
本系列教程涉及独立 Docker 容器的网络。有关与 swarm 服务联网的信息,请参阅 与 swarm 服务联网。如果您需要了解有关 Docker 网络的更多一般信息,请参阅概述。
本主题包括两个不同的教程。您可以在 Linux、Windows 或 Mac 上运行它们中的每一个,但对于最后一个,您需要在其他地方运行第二个 Docker 主机。
使用默认桥接网络演示了如何使用
bridge
Docker 自动为您设置的默认网络。该网络不是生产系统的最佳选择。使用用户定义的桥接网络展示了如何创建和使用您自己的自定义桥接网络,以连接在同一 Docker 主机上运行的容器。建议在生产环境中运行的独立容器使用此方法。
虽然 覆盖网络通常用于集群服务,但您也可以将覆盖网络用于独立容器。这是有关使用覆盖网络的教程的一部分 。
使用默认桥接网络
在此示例中,您alpine
在同一 Docker 主机上启动两个不同的容器并进行一些测试以了解它们如何相互通信。您需要安装并运行 Docker。
打开终端窗口。在执行其他操作之前先列出当前网络。如果您从未在此 Docker 守护进程上添加过网络或初始化过 swarm,那么您应该看到以下内容。您可能会看到不同的网络,但您至少应该看到这些(网络 ID 会不同):
$ docker network ls NETWORK ID NAME DRIVER SCOPE 17e324f45964 bridge bridge local 6ed54d316334 host host local 7092879f2cc8 none null local
列出了默认
bridge
网络以及host
和none
。后两者不是成熟的网络,而是用于启动直接连接到 Docker 守护进程主机的网络堆栈的容器,或启动没有网络设备的容器。本教程将两个容器连接到bridge
网络。Start two
alpine
containers runningash
, which is Alpine's default shell rather thanbash
. The-dit
flags mean to start the container detached (in the background), interactive (with the ability to type into it), and with a TTY (so you can see the input and output). Since you are starting it detached, you won't be connected to the container right away. Instead, the container's ID will be printed. Because you have not specified any--network
flags, the containers connect to the defaultbridge
network.$ docker run -dit --name alpine1 alpine ash $ docker run -dit --name alpine2 alpine ash
Check that both containers are actually started:
$ 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
Inspect the
bridge
network to see what containers are connected to it.$ 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": {} } ]
Near the top, information about the
bridge
network is listed, including the IP address of the gateway between the Docker host and thebridge
network (172.17.0.1
). Under theContainers
key, each connected container is listed, along with information about its IP address (172.17.0.2
foralpine1
and172.17.0.3
foralpine2
).The containers are running in the background. Use the
docker attach
command to connect toalpine1
.$ docker attach alpine1 / #
The prompt changes to
#
to indicate that you are theroot
user within the container. Use theip addr show
command to show the network interfaces foralpine1
as they look from within the container:# 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
The first interface is the loopback device. Ignore it for now. Notice that the second interface has the IP address
172.17.0.2
, which is the same address shown foralpine1
in the previous step.From within
alpine1
, make sure you can connect to the internet by pinginggoogle.com
. The-c 2
flag limits the command to twoping
attempts.# ping -c 2 google.com PING google.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 --- google.com ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 9.841/9.869/9.897 ms
Now try to ping the second container. First, ping it by its IP address,
172.17.0.3
:# 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
This succeeds. Next, try pinging the
alpine2
container by container name. This will fail.# ping -c 2 alpine2 ping: bad address 'alpine2'
Detach from
alpine1
without stopping it by using the detach sequence,CTRL
+p
CTRL
+q
(hold downCTRL
and typep
followed byq
). If you wish, attach toalpine2
and repeat steps 4, 5, and 6 there, substitutingalpine1
foralpine2
.Stop and remove both containers.
$ docker container stop alpine1 alpine2 $ docker container rm alpine1 alpine2
Remember, the default bridge
network is not recommended for production. To
learn about user-defined bridge networks, continue to the
next tutorial.
Use user-defined bridge networks
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-net
网络。您不需要该--driver bridge
标志,因为它是默认的,但此示例显示了如何指定它。$ docker network create --driver bridge alpine-net
列出 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 地址可能有所不同。创建四个容器。注意
--network
标志。该命令期间只能连接到一个网络docker run
,因此您还需要 在执行命令docker network connect
后使用该命令来连接alpine4
该bridge
网络。$ 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
再次检查
bridge
网络和网络: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
连接到bridge
网络。$ 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
网络。在用户定义的网络上
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
从
alpine1
,您应该根本无法连接到alpine3
,因为它不在alpine-net
网络上。# ping -c 2 alpine3 ping: bad address 'alpine3'
不仅如此,您也无法通过其 IP 地址连接到
alpine3
from 。alpine1
回头查看网络docker network inspect
的输出bridge
并找到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
alpine1
使用分离序列CTRL
+p
CTRL
+进行分离q
(按住CTRL
并键入,p
然后输入q
)。请记住,它
alpine4
已连接到默认bridge
网络和alpine-net
.它应该能够到达所有其他容器。但是,您需要alpine3
使用其 IP 地址进行寻址。连接到它并运行测试。$ 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
作为最终测试,确保您的容器都可以通过 ping 连接到互联网
google.com
。你已经爱上了,alpine4
所以从那里开始尝试。接下来,断开连接alpine4
并连接到alpine3
(仅连接到bridge
网络),然后重试。最后,连接到alpine1
(仅连接到网络alpine-net
)并重试。# ping -c 2 google.com PING google.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 --- google.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 google.com PING google.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 --- google.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 google.com PING google.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 --- google.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
停止并删除所有容器和
alpine-net
网络。$ docker container stop alpine1 alpine2 alpine3 alpine4 $ docker container rm alpine1 alpine2 alpine3 alpine4 $ docker network rm alpine-net