旧版容器链接

预计阅读时间:14分钟

警告

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

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

本节中的信息说明了Docker默认bridge网络中的旧容器链接,该链接在您安装Docker时自动创建。

在使用Docker网络功能之前,您可以使用Docker链接功能,使容器彼此发现并安全地将有关一个容器的信息传输到另一个容器。通过Docker网络功能的引入,您仍然可以创建链接,但是它们在默认bridge网络和 用户定义的网络之间的行为有所不同。

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

使用网络端口映射进行连接

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

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

注意:容器具有内部网络和IP地址。Docker可以具有多种网络配置。您可以在此处查看有关Docker网络的更多信息。

创建该容器时,该-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绑定到主机上localhost127.0.0.1接口上的端口80 。

或者,要将容器的端口5000绑定到动态端口(但仅在上) localhost,则可以使用:

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

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

$ 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可以多次使用该标志来配置多个端口。

与链接系统连接

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

网络端口映射并不是Docker容器可以相互连接的唯一方式。Docker还具有一个链接系统,使您可以将多个容器链接在一起,并将连接信息从一个容器发送到另一个容器。链接容器后,可以将有关源容器的信息发送到收件人容器。这使收件人可以看到描述源容器各方面的选定数据。

命名的重要性

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

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

  2. 它为Docker提供了一个参考点,该参考点允许Docker引用其他容器,例如,您可以指定将容器链接web到container 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),然后才能创建具有相同名称的新容器。另外,您也可以--rmdocker run命令中使用该标志。这将在容器停止后立即删除它。

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

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

db将从training/postgres 图像中创建一个新容器,该容器包含一个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容器时,我们没有使用-Por-p标志。链接的一大好处是:我们不需要将源容器(这里是PostgreSQL数据库)公开到网络。

Docker通过两种方式将源容器的连接信息公开给接收者容器:

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

环境变量

链接容器时,Docker将创建多个环境变量。Docker根据这些--link参数在目标容器中自动创建环境变量。它还从源容器中公开了所有源自Docker的环境变量。这些变量包括:

  • ENV在源容器的Dockerfile命令
  • -e--env--env-file在选择docker run 命令时,源容器开始

这些环境变量允许从目标容器内以编程方式发现与源容器有关的信息。

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

Docker<alias>_NAME--link参数中列出的每个目标容器设置一个环境变量。例如,如果一个名为的新容器 web链接到一个名为dbvia的数据库容器--link db:webdb,那么Doc​​ker将WEBDB_NAME=/web/webdb在该web容器中创建一个变量。

Docker还为源容器暴露的每个端口定义了一组环境变量。每个变量具有以下形式的唯一前缀:

<name>_PORT_<port>_<protocol>

此前缀中的组件是:

  • 参数中<name>指定的别名--link(例如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容器通信。

有关Docker环境变量的重要说明

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

这些环境变量仅在容器中的第一个过程中设置。生成守护程序sshd进行连接时,某些守护程序(例如)会清理它们。

更新/etc/hosts文件

除了环境变量外,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

您可以看到两个相关的主机条目。第一个是web 使用Container ID作为主机名的容器条目。第二项使用链接别名来引用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命令,db使用其主机条目ping到容器,该主机条目解析为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
示例用法用户指南链接链接docker文档示例名称名称容器命名端口地图网络端口网络