使用独立容器联网
本系列教程介绍独立 Docker 容器的联网。 有关使用 swarm 服务联网的信息,请参阅使用 swarm 服务联网。如果您需要 了解有关 Docker 网络的更多信息,请参阅概述。
本主题包括两个不同的教程。您可以在 Linux、Windows 或 Mac,但对于最后一个,您需要第二个 Docker 主机在其他地方运行。
使用默认桥接网络演示 如何使用 Docker 为您设置的默认网络 自然而然。此网络不是生产系统的最佳选择。
bridge
使用用户定义的桥接网络 shows 如何创建和使用您自己的自定义桥接网络来连接容器 在同一 Docker 主机上运行。建议对独立容器执行此操作 在生产环境中运行。
尽管覆盖网络通常用于 swarm 服务, 您还可以将覆盖网络用于独立容器。这包括 有关使用叠加网络的教程的一部分。
使用默认桥接网络
在此示例中,您将在同一 Docker 上启动两个不同的容器
host 并执行一些测试以了解它们如何相互通信。你
需要安装并运行 Docker。alpine
打开终端窗口。在执行任何其他操作之前,请先列出当前网络。 如果您从未添加过网络或初始化过 swarm 的 Docker 守护程序。您可能会看到不同的网络,但您应该看到 至少看到这些(网络 ID 会有所不同):
$ docker network ls NETWORK ID NAME DRIVER SCOPE 17e324f45964 bridge bridge local 6ed54d316334 host host local 7092879f2cc8 none null local
将列出默认网络以及 和 。这 后两者不是成熟的网络,但用于启动容器 直接连接到 Docker 守护程序主机的网络堆栈,或启动 没有网络设备的容器。本教程将连接两个 容器连接到网络。
bridge
host
none
bridge
启动两个运行 的容器,这是 Alpine 的默认 shell 而不是 .flags 表示启动容器分离 (在后台)、交互式(能够在其中键入内容)和 替换为 TTY(以便您可以看到输入和输出)。既然你正在启动它 detachd,则不会立即连接到容器。相反, 将打印容器的 ID。由于您尚未指定任何标志,因此容器将连接到默认网络。
alpine
ash
bash
-dit
--network
bridge
$ 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
检查网络以查看连接到它的容器。
bridge
$ 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 地址 ()。在密钥下,每个连接的容器 ,以及有关其 IP 地址的信息( for 和 for )。
bridge
bridge
172.17.0.1
Containers
172.17.0.2
alpine1
172.17.0.3
alpine2
容器在后台运行。使用命令连接到 。
docker attach
alpine1
$ docker attach alpine1 / #
提示将更改为,以指示您是 容器。使用命令显示网络接口 因为 as they look from the container (从容器内看):
#
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
第一个接口是 loopback 设备。暂时忽略它。请注意, 第二个接口的 IP 地址相同 地址。
172.17.0.2
alpine1
从 内部 ,确保您可以通过以下方式连接到 Internet ping .该标志将命令限制为两次尝试。
alpine1
google.com
-c 2
ping
# 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
现在尝试 ping 第二个容器。首先,通过其 IP 地址 ping 它:
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
这成功了。接下来,尝试逐个容器 ping 容器 名字。这将失败。
alpine2
# ping -c 2 alpine2 ping: bad address 'alpine2'
使用 detach 序列 + +(按住并键入,后跟 )分离而不停止它。 如果您愿意,请在此处附加并重复步骤 4、5 和 6。 替换 .
alpine1
CTRL
p
CTRL
q
CTRL
p
q
alpine2
alpine1
alpine2
停止并移除两个容器。
$ docker container stop alpine1 alpine2 $ docker container rm alpine1 alpine2
请记住,不建议将默认网络用于生产。自
了解 User-Defined Bridge Networks,请继续学习下一教程。bridge
使用用户定义的桥接网络
在此示例中,我们再次启动两个容器,但将它们附加到
用户定义的网络。这些
容器根本没有连接到默认网络。然后
启动第三个容器,该容器已连接到网络,但
未连接到 ,以及第四个容器,即
连接到两个网络。alpine
alpine-net
bridge
alpine
bridge
alpine-net
alpine
创建网络。您不需要标志 因为它是默认值,但此示例显示了如何指定它。
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
检查网络。这将向您显示其 IP 地址和事实 没有容器连接到它:
alpine-net
$ 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": {} } ]
请注意,此网络的网关是 ,而不是 default 桥接网络,其网关为 。确切的 IP 地址 在您的系统上可能有所不同。
172.18.0.1
172.17.0.1
创建您的四个容器。请注意标志。您只能 在命令期间连接到一个网络,因此您还需要使用 afterward 连接到网络。
--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
在用户定义的网络上,容器不仅可以 通过 IP 地址进行通信,但也可以将容器名称解析为 IP 地址。此功能称为自动服务发现。让我们 连接到 并对此进行测试。 应该能够解析 and(以及 , 本身)到 IP 地址。
alpine-net
alpine1
alpine1
alpine2
alpine4
alpine1
注意
自动服务发现只能解析自定义容器名称,不能解析默认自动生成的容器名称。
$ 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 连接到 地址。回头查看网络的输出并找到 的 IP 地址:尝试 ping 它。
alpine3
alpine1
docker network inspect
bridge
alpine3
172.17.0.2
# 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
使用 detach sequence + +(按住并键入,后跟 )进行分离。
alpine1
CTRL
p
CTRL
q
CTRL
p
q
请记住,它连接到默认网络 和。它应该能够到达所有其他容器。 但是,您需要通过其 IP 地址进行寻址。附加到它 并运行测试。
alpine4
bridge
alpine-net
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
作为最终测试,请确保您的容器都可以连接到 Internet 通过 ping .您已经依恋好了,所以从 从那里开始尝试。接下来,分离并连接到(仅连接到网络),然后重试。最后 Connect To (仅连接到网络) 然后重试。
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