本文介绍安装docker时自动创建的docker默认bridge网络内的旧的容器链接(links)。–link标志是docker废弃的旧功能。它可能会最终被删除。除非你真的需要继续使用它,否则我们推荐你使用用户定义网络来连通两个容器之间的网络,而不是使用–link。用户定义网络有一个功能不支持而可以使用–link来启用的是容器之间环境变量的共享。不过你可以使用其它的机制如volumes来以更可控的方式在容器之间共享环境变量。
使用网络端口映射连接
下面是创建一个容器来运行一个Python Flask应用:
- $ docker run -d -P training/webapp python app.py
当容器创建后,-P参数用来自动地将创建容器的Dockerfile中EXPOSE的端口映射到你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参数把容器端口绑定到主机上的一个指定端口。
下面示例中容器的5000端口映射到主机的80端口:
- $ 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参数指定绑定一个固定的端口到所有的网络接口,你也可以指定绑定一个特定接口,如只绑定到localhost。
- $ docker run -d -p 127.0.0.1:80:5000 training/webapp python app.py
或者绑定主机接口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来显示容器指定的端口绑定详情。
- $ docker port nostalgic_morse 5000
- 127.0.0.1:49155
注意:-p参数可以使用多次来绑定多个端口。
使用链接系统连接
注意:本节只覆盖默认的bridge网络下的旧链接功能,不涉及到用户定义网络下的链接(link)。
网络端口映射不是docker容器能彼此连接的唯一一种方式。Docker还有一个链接系统(linking system)允许你把多个容器链接到一起并彼此发送连接信息。当容器被链接时,这个容器的连接信息将发送到主动链接的容器中。
命名的重要性
要建立链接,Docker依赖容器的名称。如果不指定容器名称,docker将自动创建一个随机的名称;容器名称有两个有用的功能:
1.你可以根据容器所做的任务来命名它帮助你容易地记住这个容器是做什么的,如命名一个web应用程序为web。
2.你可以使用容器名称来引用它,如可以指定链接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
链接间通信
链接允许容器彼此发现并安全地传输关于彼此连接的信息。当你配置一个链接时,你就在被链接容器和链接容器之间创建了一个管道。然后链接容器就能访问关于被链接容器的数据。我们使用–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
链接标志的格式:
- –link <name or id>:alias
其中name是我们要链接到的容器名称,alias是链接名称的别名。也有缩写的格式,如:
- –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。使用链接,容器间通信就不需要通过-p或-P来把端口绑定到主机上。docker在容器间创建一个安全的隧道用来链接容器间通信。
docker通过以下两种方式来把被链接容器的连接信息暴露给链接容器:
环境变量
当你链接容器时Docker将创建一些环境变量。Docker根据–link参数来在链接容器中自动创建环境变量。它也把被链接的容器从Docker设置的环境变量设置给链接容器。这些环境变量包括:
Docker为每个链接容器设置一个_NAME环境变量。例如,如果一个新的容器称为web通过–link db:webdb链接到一个数据库容器称为db,那么Docker将在web容器创建一个WEBDB_NAME=/web/webdb变量。
Docker也根据被链接容器暴露的每一个端口设置了一组环境变量。每个变量有一个唯一的前缀,格式为:
_PORT__
前缀的组成是:
docker使用这个前缀来定义三个唯一的环境变量:
WEBDB_PORT_5432_TCP_ADDR=172.17.0.82
WEBDB_PORT_5432_TCP_PORT=5432
WEBDB_PORT_5432_TCP_PROTO=tcp
如果一个容器暴露了多个端口,那么将会为每个端口设置一组环境变量。例如,一个容器暴露4个端口,那么docker将创建12个环境变量,每个端口3个。
此外,docker创建一个环境变量称为_PORT。这个变量包含容器第一个暴露的端口的URL。如WEBDB_PORT=tcp://172.17.0.82:5432。
最后,docker也把被链接容器的每一个原始环境变量设置为链接容器的环境变量,变量格式为_ENV_。
你可以执行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环境变量重要提示
不像在/etc/hosts文件的主机条目,存储在环境变量的IP地址在被链接容器重启时不会自动更新。我们推荐使用/etc/hosts文件中的主机条目来解析被链接容器的IP地址。
这些环境变量只为容器的第一个进程设置。一些daemon,如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地址。除了链接别名,如果链接别名与被链接容器名不一样,那么还添加被链接容器名与其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
如果你重启了被链接容器,那么链接容器的/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