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/>
相关文章推荐
- Opencv鼠标事件下的ROI
- iOS7 CookBook精彩瞬间(一)property、selector细节、__unused
- HDU1301 最小生成树kruskal裸题
- 树莓派安装操作系统-raspbian的方法
- jedis使用样例程序
- epoll实现分析
- Node.js socketio一对一客服系统
- Liunx学习笔记--基本网络设定(测试内容)
- 二叉树的java实现
- SYN Flood攻击防范技术(转)
- Codeforces Round #318 [RussianCodeCup Thanks-Round] (Div. 2)
- Servlet3.0
- 列表下拉/上拉刷新:(三)强制刷新
- leetcode刷题,总结,记录,备忘 268
- UI Design
- .net学习笔记----会话状态Session
- HDU 1018 Big Number(斯特林公式)
- Unity3D有限状态机(FSM)学习笔记【7】使用实例
- 树莓派RaspBian的设置与引导
- Opencv鼠标截取图片场景