container之间建立连接
在Docker使用章节,你看到如何通过network port 连接运行在Docker container中的服务。但是端口连接只是一种与运行在Docker container中的服务或者应用互动的方式。在本节 ,我们将简单的回复建立network port连接的方式,然后介绍另外一种访问方式:container linking。Network port映射回顾 在Dock
在Docker使用章节,你看到如何通过network port 连接运行在Docker container中的服务。但是端口连接只是一种与运行在Docker container中的服务或者应用互动的方式。在本节 ,我们将简单的回复建立network port连接的方式,然后介绍另外一种访问方式:container linking。
Network port映射回顾
在Docker使用章节,我们创建了一个container来运行Python Flask应用。
$ sudo docker run -d -P training/webapp python app.py
注意:containers有内部网络和IP地址(使用docker inspect命令看到container的IP地址)。Docker有不同的网络配置。我们可以在
这里查看网络配置。
当容器被创建,-P用于自动将网络端口映射到主机在49153到65535之间的任意端口。接下来,运行docker ps
$ sudo 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
你也可以显示的指定container端口绑定的主机端口,使用-p标签。
$ sudo docker run -d -p 5000:5000 training/webapp python app.py
我们看到这不是一个好主意,因为这约束我们只能一个容器能够指定到这个特定端口上。
有一些其他的方法使用-p标签来配置。默认,-p标签将绑定特定的端口到所有的在主机上的接口。但是我们也可以指定绑定特定的接口,例如只到localhost。
$ sudo docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
这将绑定container的内部5000端口到在主机上接口为localhost或者127.0.0.1的接口上的5000端口。
或者,动态绑定容器的5000端口到localhost上,可以这样做:
$ sudo docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
我们可以使用docker port快捷方式查询当前绑定的端口。
这是一个有用的方法来显示指定端口的配置。例如,如果你已经绑定容器的端口到主机上的localhost。那么docker port将输出这个结果。
$ sudo docker port nostalgic_morse 5000
127.0.0.1:49155
注意:-p标签可以使用多次来配置多个端口。
Docker Container Linking
网络端口的映射不是唯一的方法使一个container访问另外一个container。Docker也具有一个linking system,我们可以将多个container连接在一起,相互之间发送连接信息。当container被连接,关于来源container的信息将被发送给接收container。这将是接收信息放能够看到来源container的信息。
Container naming
为了建立连接,Docker依赖Container的名字。你已经看到了每一个容器都有一个自动创建的名字。你也可以自己命名这个Container名字。这个命令提供了两种功能:
- 用名字表示这个Container特定功能的一种方法,使你更容易的记住它们。例如,命名包含一个wen应用的Container为web。
- 提供了Docker一个参考点,让其他容器容易索引到它,例如,你可以指定web容器连接到db容器。
可以使用--name标签命名容器,例如:
$ sudo docker run -d -P --name web training/webapp python app.py
启动了Container,命名为--name这个容器为web。你可以使用docker ps命令查看这个容器的名字。
$ sudo 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 来返回Container的名字。
$ sudo docker inspect -f "{{ .Name }}" aed84ee21bde
/web
注意:Container名字必须是独一无二的。那么只能命名一个Container为web。如果你想要重新使用一个容器名字,必须删除原来的Container(用docker rm),然后才能创建同名的新Container。作为一种替代方案,在docker run命令中使用--rm标签,这将在Container停止后立即删除。
Container Linking
连接让Container发现彼此,安全的传输信息。当我们建立连接,可以在来源Container和接收Container之间建立导管。这个接收方可以访问选择的关于来源方的数据。为了创建 连接,使用--link标签。首先,创建一个容器,这次一个包含数据库。
$ sudo docker run -d --name db training/postgres
创建了一个新的Container叫做db,来自training/postgres image,它包含PostgreSQL 数据库。
现在,你需要删除web Container,这样才可一个创建一个linked Container来代替:
$ sudo docker rm -f web
现在创建一个web Container,与db Container连接起来。
$ sudo docker run -d -P --name web --link db:db training/webapp python app.py
这将连接新的web Container到之前创建的db Container。这个--link标签的形成:
--link <name or id>:alias
name是想要连接Container的名字,alias是link的名字的别名。
你将看到别名为什么是名字缩小。
下一步,检查被连接的Container,使用docker inspect:
$ sudo docker inspect -f "{{ .HostConfig.Links }}" web
[/db:/web/db]
你可以看到web Container已经已经与db Container建立连接 web/db。这个允许web Container访问dbContainer的信息。
那么两个连接的Container做了什么呢?连接时来源Container提供信息给接收Container。在我们的例子中,接收方web,可以访问关于来源方db的信息。为了实现这个,docker创建在容器之间创建一个安全通道,不需要向外界暴露任何端口。在我们启动db Container时,没有使用任何-P或者-p标签。这就是连接的益处:我不需要去网络中暴露我们来源Container,这里PostgreSQL数据库。
Docker暴露来源容器的连接信息给接收容器,有两种方法:
- 环境变量
- 更新/etc/hosts文件
- <name>_PORT_<port>_<protocol>将包含一个URL索引到这个端口。<name>是在--link参数指定的 别名,(例如webdb),<port>是被暴露的端口号,<protocol>是TCP或者UDP。URL的格式如下:<protocol>://<container_ip_address>:<port>(例如tcp://172.17.0.82:8080)。这个URL为了便于使用被分为3个环境变量:
- <name>_PORT_<port>_<portocol>_ADDR包含URL的IP地址(例如WEBDB_PORT_8080_TCP_ADDR=172.17.0.82)。
- <name>_PORT_<port>_<portocol>_PORT包含URL端口号(例如WEBDB_PORT_8080_TCP_PORT=8080)。
- <name>_PORT_<port>_<portocol>_PRPTO包含URL协议(例如WEBDB_PORT_8080_TCP_PROTO=tcp)。
如果多个端口被暴露,则以上的环境变量设置将为每个端口设置。
最后,被称为<alias>_PORT的环境变量将包含第一个源容器暴露的URL。例如WEBD_PORT=tcp://172.17.0.82:8080。在这个例子中,‘first’被定义为被暴露的最小端口编号。如果端口被用于tcp和udp,那么tcp端口被指定。
返回到我们数据库的例子,你可以运行env命令来罗列指定的容器环境变量。
$ sudo 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
. . .
注意:这些环境变量只是配置给Container的第一个进程。
Similarly, some daemons (such as
sshd
) will scrub them when spawning shells for connection.
注意:不像在/etc/hosts文件中的host条目,IP地址储存在环境变量中,不能自动的更新如果源Container重启了。所以建议使用在/etc/hosts/中的host条目来解决被连接的容器之间的IP问题。
你可以看到创建有用信息的环境变量关于db容器。每一个环境变量带前缀DB_,这来源于指定的别名。如果alias是db1,那么变量将以DB1_为前缀。你可以使用这些环境变量来配置的应用来连接到在db容器上的数据库。这个连接是安全的和私有的。只有被连接web容器能够与db容器通信。
更新/etc/hosts文件
除了环境变量,Docker可以在源容器的,/etc/hosts文件上添加host entity。这是web容器的目录:
$ sudo 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.5 db
你可以看到两个相关的host目录。第一个目录是web容器将Container ID作为主机名字。第二个目录使用连接别名,索引到db容器的IP地址。你可以通过ping这个主机名。
root@aed84ee21bde:/opt/webapp# apt-get install -yqq inetutils-ping
root@aed84ee21bde:/opt/webapp# ping db
PING db (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容器,使用它的host目录,解析为172.17.0.5。你可以使用这个host条目配置应用,从而使用db容器。
注意:你可以连接多个接收容器到单个来源。例如你可以有多个不同名字的web容器连接到db容器上。
如果你重启了源容器,被连接的容器/etc/hosts文件将被自动更新为新源容器的IP地址,来继续保持通讯。
$ sudo docker restart db
db
$ sudo 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
更多推荐
所有评论(0)