Legacy container links

预计阅读时间:14分钟

Warning

--link标志是 Docker 的遗留功能. 它最终可能会被删除. 除非您绝对需要继续使用它,否则我们建议您使用用户定义的网络来促进两个容器之间的通信,而不是使用--link . 用户定义的网络不支持您可以使用--link执行的一项功能是在容器之间共享环境变量. 但是,您可以使用其他机制(例如卷)以更可控的方式在容器之间共享环境变量.

有关使用--link的一些替代方法,请参阅用户定义的网桥和默认网桥之间的差异.

本节中的信息解释了安装 Docker 时自动创建的 Docker 默认bridge网络中的旧容器链接.

Docker 网络功能之前,您可以使用 Docker 链接功能来允许容器相互发现并将有关一个容器的信息安全地传输到另一个容器. 随着 Docker 网络功能的引入,您仍然可以创建链接,但它们在默认bridge网络和用户定义网络之间的行为不同.

本节简要讨论通过网络端口进行连接,然后详细介绍默认bridge网络中的容器链接.

Connect using network port mapping

假设您使用此命令运行一个简单的 Python Flask 应用程序:

$ docker run -d -P training/webapp python app.py

Note: Containers have an internal network and an IP address. Docker can have a variety of network configurations. You can see more information on Docker networking here.

创建该容器时,使用-P标志将其中的任何网络端口自动映射到 Docker 主机上的临时端口范围内的随机高端口. 接下来,当docker ps运行时,您看到容器中的 5000 端口绑定到主机上的 49155 端口.

$ docker ps nostalgic_morse

CONTAINER ID  IMAGE                   COMMAND       CREATED        STATUS        PORTS                    NAMES
bc533791f3f5  training/webapp:latest  python app.py 5 seconds ago  Up 2 seconds  0.0.0.0:49155->5000/tcp  nostalgic_morse

您还看到了如何使用-p标志将容器的端口绑定到特定端口. 这里主机的 80 端口映射到容器的 5000 端口:

$ docker run -d -p 80:5000 training/webapp python app.py

你明白了为什么这不是一个好主意,因为它把你限制在那个特定端口上只有一个容器.

相反,您可以指定一系列主机端口以将容器端口绑定到与默认临时端口范围不同的端口:

$ docker run -d -p 8000-9000:5000 training/webapp python app.py

这会将容器中的端口 5000 绑定到主机上 8000 到 9000 之间的随机可用端口.

还有一些其他方法可以配置-p标志. 默认情况下, -p标志将指定端口绑定到主机上的所有接口. 但您也可以指定绑定到特定接口,例如仅绑定到localhost .

$ docker run -d -p 127.0.0.1:80:5000 training/webapp python app.py

这会将容器内的端口 5000 绑定到localhost上的端口 80 或主机上的127.0.0.1接口.

或者,要将容器的端口 5000 绑定到动态端口,但只能在localhost上,您可以使用:

$ docker run -d -p 127.0.0.1::5000 training/webapp python app.py

您还可以通过添加尾随/udp/sctp来绑定 UDP 和 SCTP(通常由 SIGTRAN、Diameter 和 S1AP/X2AP 等电信协议使用)端口. 例如:

$ docker run -d -p 127.0.0.1:80:5000/udp training/webapp python app.py

您还了解了有用的docker port快捷方式,它向我们展示了当前的端口绑定. 这对于向您显示特定的端口配置也很有用. 例如,如果您已将容器端口绑定到主机上的localhost ,则docker port输出会反映这一点.

$ docker port nostalgic_morse 5000

127.0.0.1:49155

注意-p标志可以多次使用来配置多个端口.

Connect with the linking system

注意:本节介绍默认bridge网络中的旧链接功能. 有关用户定义网络中链路的更多信息,请参阅用户定义网桥和默认网桥之间的差异.

网络端口映射并不是 Docker 容器相互连接的唯一方式. Docker 还有一个链接系统,允许您将多个容器链接在一起并将连接信息从一个容器发送到另一个容器. 当容器被链接时,关于源容器的信息可以被发送到接收容器. 这允许接收者看到描述源容器方面的选定数据.

The importance of naming

为了建立链接,Docker 依赖于容器的名称. 您已经看到您创建的每个容器都有一个自动创建的名称. 在本指南中,您确实已经熟悉了我们的老朋友nostalgic_morse . 您也可以自己命名容器. 这种命名提供了两个有用的功能:

  1. 以更容易记住它们的方式命名执行特定功能的容器可能很有用,例如命名包含 Web 应用程序web的容器.

  2. 它为 Docker 提供了一个引用点,允许它引用其他容器,例如,您可以指定将容器web链接到容器db .

您可以使用--name标志来命名您的容器,例如:

$ docker run -d -P --name web training/webapp python app.py

这会启动一个新容器并使用--name标志来命名容器web . 您可以使用docker ps命令查看容器的名称.

$ docker ps -l

CONTAINER ID  IMAGE                  COMMAND        CREATED       STATUS       PORTS                    NAMES
aed84ee21bde  training/webapp:latest python app.py  12 hours ago  Up 2 seconds 0.0.0.0:49154->5000/tcp  web

您还可以使用docker inspect来返回容器的名称.

注意:容器名称必须是唯一的. 这意味着您只能调用一个容器web . 如果要重复使用容器名称,则必须先删除旧容器(使用docker container rm ),然后才能创建具有相同名称的新容器. 作为替代方案,您可以将--rm标志与 docker docker run命令一起使用. 这会在容器停止后立即删除它.

链接允许容器相互发现并将有关一个容器的信息安全地传输到另一个容器. 设置链接时,您会在源容器和接收容器之间创建管道. 然后接收者可以访问关于源的选择数据. 要创建链接,请使用--link标志. 首先,创建一个新容器,这次是一个包含数据库的容器.

$ docker run -d --name db training/postgres

这会从training/postgres映像创建一个名为db的新容器,其中包含一个 PostgreSQL 数据库.

现在,您需要删除之前创建的web容器,以便将其替换为链接的容器:

$ docker container rm -f web

现在,创建一个新的web容器并将其与您的db容器链接.

$ docker run -d -P --name web --link db:db training/webapp python app.py

这会将新的web容器与您之前创建的db容器链接起来. --link标志采用以下形式:

--link <name or id>:alias

其中name是我们要链接到的容器的名称,而alias是链接名称的别名. 该别名很快就会使用. --link标志也采用以下形式:

--link <name or id>

在这种情况下,别名与名称匹配. 您可以将前面的示例编写为:

$ docker run -d -P --name web --link db training/webapp python app.py

接下来,使用docker inspect检查链接的容器:

$ docker inspect -f "{{ .HostConfig.Links }}" web

[/db:/web/db]

您可以看到web容器现在已链接到db容器web/db . 这允许它访问有关db容器的信息.

那么链接容器实际上是做什么的呢? 您已经了解到,链接允许源容器向接收容器提供有关其自身的信息. 在我们的示例中,收件人web可以访问有关源db的信息. 为此,Docker 在容器之间创建了一个安全隧道,不需要在容器外部公开任何端口; 当我们启动db容器时,我们没有使用-P-p标志. 这是链接的一大好处:我们不需要将源容器(这里是 PostgreSQL 数据库)暴露给网络.

Docker 以两种方式将源容器的连接信息暴露给接收容器:

  • 环境变量,
  • 更新/etc/hosts文件.

Environment variables

当您链接容器时,Docker 会创建几个环境变量. Docker 根据--link参数自动在目标容器中创建环境变量. 它还公开了源容器中源自 Docker 的所有环境变量. 这些包括来自以下的变量:

  • 源容器的 Dockerfile 中的ENV命令
  • 启动源容器时 docker docker run命令上的-e--env--env-file选项

这些环境变量支持从目标容器内以编程方式发现与源容器相关的信息.

警告:重要的是要了解容器中源自 Docker 的所有环境变量都可用于链接到它的任何容器. 如果敏感数据存储在其中,这可能会产生严重的安全隐患.

Docker 为--link参数中列出的每个目标容器设置一个<alias>_NAME环境变量. 例如,如果一个名为web的新容器通过--link db:webdb链接到一个名为db的数据库容器,则 Docker 在web容器中创建一个WEBDB_NAME=/web/webdb变量.

Docker 还为源容器公开的每个端口定义了一组环境变量. 每个变量都有一个唯一的前缀,格式如下:

<name>_PORT_<port>_<protocol>

The components in this prefix are:

  • --link参数中指定的别名<name> (例如, webdb
  • <port>号码暴露
  • 一个<protocol>是 TCP 或 UDP

Docker 使用这种前缀格式来定义三个不同的环境变量:

  • prefix_ADDR变量包含来自 URL 的 IP 地址,例如WEBDB_PORT_5432_TCP_ADDR=172.17.0.82 .
  • prefix_PORT变量仅包含来自 URL 的端口号,例如WEBDB_PORT_5432_TCP_PORT=5432 .
  • prefix_PROTO变量仅包含来自 URL 的协议,例如WEBDB_PORT_5432_TCP_PROTO=tcp .

如果容器公开多个端口,则为每个端口定义一个环境变量集. 这意味着,例如,如果一个容器公开了 4 个端口,那么 Docker 会创建 12 个环境变量,每个端口 3 个.

此外,Docker 创建了一个名为<alias>_PORT的环境变量. 此变量包含源容器的第一个公开端口的 URL. "第一个"端口被定义为具有最小编号的公开端口. 例如,考虑WEBDB_PORT=tcp://172.17.0.82:5432变量. 如果该端口同时用于 tcp 和 udp,则指定 tcp 端口.

最后,Docker 还将源容器中的每个源自 Docker 的环境变量公开为目标中的环境变量. 对于每个变量,Docker 在目标容器中创建一个<alias>_ENV_<name>变量. 变量的值设置为 Docker 在启动源容器时使用的值.

回到我们的数据库示例,您可以运行env命令来列出指定容器的环境变量.

$ docker run --rm --name web2 --link db:db training/webapp env

<...>
DB_NAME=/web2/db
DB_PORT=tcp://172.17.0.5:5432
DB_PORT_5432_TCP=tcp://172.17.0.5:5432
DB_PORT_5432_TCP_PROTO=tcp
DB_PORT_5432_TCP_PORT=5432
DB_PORT_5432_TCP_ADDR=172.17.0.5
<...>

您可以看到 Docker 创建了一系列环境变量,其中包含有关源db容器的有用信息. 每个变量都以DB_为前缀,它是从您在上面指定的alias中填充的. 如果aliasdb1 ,则变量将以DB1_为前缀. 您可以使用这些环境变量来配置您的应用程序以连接到db容器上的数据库. 连接安全且私密; 只有链接的web容器可以与db容器通信.

Important notes on Docker environment variables

/etc/hosts文件中的主机条目不同,如果源容器重新启动,存储在环境变量中的 IP 地址不会自动更新. 我们建议使用/etc/hosts中的主机条目来解析链接容器的 IP 地址.

这些环境变量只为容器中的第一个进程设置. 一些守护进程,例如sshd ,会在生成 shell 以进行连接时清理它们.

Updating the /etc/hosts file

除了环境变量之外,Docker 还将源容器的主机条目添加到/etc/hosts文件中. 这是web容器的条目:

$ docker run -t -i --rm --link db:webdb training/webapp /bin/bash

root@aed84ee21bde:/opt/webapp# cat /etc/hosts
172.17.0.7  aed84ee21bde
<...>
172.17.0.5  webdb 6e5cdeb2d300 db

您可以看到两个相关的主机条目. 第一个是使用 Container ID 作为主机名的web容器条目. 第二个条目使用链接别名来引用db容器的 IP 地址. 除了您提供的别名之外,链接容器的名称(如果与提供给--link参数的别名不同)以及链接容器的主机名也将添加到/etc/hosts以获取链接容器的 IP 地址. 您可以通过以下任何条目 ping 该主机:

root@aed84ee21bde:/opt/webapp# apt-get install -yqq inetutils-ping
root@aed84ee21bde:/opt/webapp# ping webdb

PING webdb (172.17.0.5): 48 data bytes
56 bytes from 172.17.0.5: icmp_seq=0 ttl=64 time=0.267 ms
56 bytes from 172.17.0.5: icmp_seq=1 ttl=64 time=0.250 ms
56 bytes from 172.17.0.5: icmp_seq=2 ttl=64 time=0.256 ms

注意:在示例中,您必须安装ping ,因为它最初并未包含在容器中.

在这里,您使用ping命令使用其主机条目 ping db容器,该条目解析为172.17.0.5 . 您可以使用此主机条目来配置应用程序以使用您的db容器.

注意:您可以将多个收件人容器链接到单个来源. 例如,您可以将多个(不同名称的)Web 容器附加到您的db容器.

如果重新启动源容器,链接容器上的/etc/hosts文件会自动更新为源容器的新 IP 地址,从而允许链接通信继续.

$ docker restart db
db

$ docker run -t -i --rm --link db:db training/webapp /bin/bash

root@aed84ee21bde:/opt/webapp# cat /etc/hosts
172.17.0.7  aed84ee21bde
<...>
172.17.0.9  db
Examples, Usage, 用户指南, links, linking, docker, documentation, examples, names, name, 容器命名, port, map, 网络端口, network

by  icopy.site