您的位置:首页 > 其它

2.2.4、容器的互联

2015-08-30 21:07 155 查看


容器的互联

《容器的使用》部分,我们看到了如何通过网络端口来访问运行在
Docker 容器内的服务。这是与docker容器内运行应用程序交互的唯一方法。在本节中,我们对之前的方法做一个简单的回顾,然后我们将介绍另外一个访问的方法:容器的链接。


使用网络端口映射链接

《容器的使用》部分,你创建一个内部运行着
Python
Flask
的应用程序的容器:
$ docker run -d -P training/webapp python app.py


注意:容器拥有一个内部网络IP地址(正如我们在《容器的使用》部分的时候,使
docker
inspect
命令查看容器的IP地址一样)。Docker可以有各种网络配置方式。你可以在这里了解到更多关于Docker网络的细节。

当容器被创建的时候,使用
-P
标志会自动的为容器内容的网络端口映射到宿主机的一个高段位的端口上,它是一个在临时端口区间随机选择的。然后,当执行
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


我们看这为什么不是一个好的主意呢?因为它限制了在一个指定端口上只能有一个容器。

我们还有很多设置
-p
标识的方法。默认情况下
-p
标志将会指定的端口映射到宿主机的所有网络接口中。但是,你也可以映射到指定的网络接口中,例如,仅仅映射到
localhost

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


这样会将容器内部的5000端口到与宿主机上的
localhost
127.0.0.1
接口的80端口进行捆绑。

或者,要将容器的5000端口仅与宿主机上的
localhost
接口的一个动态端口进行捆绑,你可以使用:
$ docker run -d -p 127.0.0.1::5000 training/webapp python app.py


你也可以通过在命令的尾部追加
/udp
绑定UDP的端口,例如:
$ 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 5000127.0.0.1:49155


注意:
-p
标志可以多次使用去设置多个端口的绑定。


通过连接系统连接

网络端口映射不是Docker容器之间互联的唯一途径。Docker容器也可以通过连接系统进行互联,进行连接信息的相互发送。当容器互联时,源容器可以发送信息到接受容器中。这样,接受端就可以看到源容器的表述方面的任何数据。


命名的重要性

为了建立连接,Docker需要依赖你容器的名字。你已经了看到,每一个容器创建后都会Docker都会自动为之生成一个名字。所以
nostalgic_morse
这个容器名字都是成为了我们老朋友了。当然,你也可以为容器命名。这个名字有连个作用:

它可以让我们的容器”见名知意“,让我们们更加容易的记住和区分它们的功能。例如,命名一个内部运行这个一个web应用的容器为
web


它为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 rm
命令)。如果你觉得麻烦,你也可以在你使用
docker
run
创建命令时追加
--rm
标志。如果它此时是停止状态的话,将会给立即删除。


通过连接进行通信

连接允许容器之间相互发现并安全的互传信息。当你建立了一个连接,相当于在两个容器之间“修建”了一条管道。为了创建一个连接,你可以使用
--link
标志。首先,创建一个新的容器,这次是一个包含数据库的容器。
$ docker run -d --name db training/postgres


在这里,基于
training/postgres
镜像创建了一个命令为
db
的新容器,它包含了一个
PostgreSQL
数据库。

现在,你要删除之前创建的
web
容器,方便你重新创建一个带连接的容器:
$ docker 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
文件


环境变量

Docker会创建几个环境变量,当你连接一个容器时。Docker利用
--link
参数自动在目标容器中创建环境变量。它将暴露源的所有环境变量,这些变量包括来自:

在源容器的Dockerfile中的
ENV
命令
在使用
docker
run
命令启动源容器时附带的
-e
--env
--env-file
选项

连接到目标源容器的容器都可以访问到这些环境变量。

警告:它帮助我们理解Docker如何使用这些环境变量,让容器之间实现互联。但是,这种模式存在一个非常严重的安全隐患,如果你的环境变量中保存了一些比较敏感的信息

Docker 会为每一个
--link
命令中的目标容器设置一个
<alias>_NAME
的环境变量。例如,如果一个
web
新容器连接到一个数据库容器
db
,使用
--link
db:webdb
指令 。之后Docker会在
web
容器里设置一个
WEBDB_NAME=/web/webdb
变量。

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
.

如果容器暴露多个端口,Docker会为它们每一个端口设置一套上述的变量定义。换句话说,例如,如果一个容器暴露了4个端口,Docker回味它创建12个环境变量,被一个端口3个定义三个变量。

除此之外,Docker还创建一个名为
<alias>_PORT
的环境变量。这个变量包含了源容器URL的第一个暴露端口。这里说的”第一个“是指在暴露端口中数值最小的那个。例如,
WEBDB_PORT=tcp://172.17.0.82:5432
变量。如果一个端口同时被指向
tcp
udp
,那么只有
tcp
生效。

最后,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
。如果你的
alias
值为
db1
,这个变量的前缀会变成
DB1_
。你可以使用这些环境变量去配置你的应用程序,让它连接到数据库容器
db
。这个连接将是安全且私有的。只有连接的
web
容器能够和
db
容器通信。


环境变量注意事项

/etc/hosts
文件中的主机条目不一样,如果源容器重启了,存储在环境变量中的IP地址是不会自动更新的。我们建议使用在
/etc/hosts
文件里的主机条目去记录连接容器的IP地址。

这些环境变量只为容器里的第一个进程设置。一些守护进程,如
sshd
,当shell连接的时候,将会擦除这些变量。


修改
/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
容器的,使用了容器的ID作为主机的名字。第二条目使用连接别名去引用
db
容器的IP地址。除了别名之外,连接容器的名字-如果这个名字在
--link
参数中是唯一的,那么这个容器名字也将会被添加到
/etc/hosts
作为连接容器的IP的主机名:
root@aed84ee21bde:/opt/webapp# apt-get install -yqq inetutils-ping
root@aed84ee21bde:/opt/webapp# ping webdb                                                                                                                             PING webdb (172.17.0.5):48 data byte
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


来源: <https://docs.docker.com/userguide/dockerlinks/>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: