Docker - 容器之间的通信

通过网络端口通信

默认情况容器和主机之间的网络通信是封闭的, 如果要让容器能够被外部网络访问, 需要在启动容器的时候指定要开放的端口, 这样我们就能通过主机的网络访问容器内提供的的服务了.我们在容器中运行了一个Web服务器,用户需要访问这个容器内的资源, 这里为了方便,直接使用官方手册里的示例:

1
root@localhost:/# docker run -d -p 5000:5000 training/webapp python app.py

命令行分解:

  • -p 标志指定了端口映射,形式为: <主机端口>:<容器端口>, 注意不要弄反了.
  • -d 标志表示让容器在后台运行
  • training/webapp 表示镜像名称
  • python app.py 表示要在容器内运行的SHELL命令

端口绑定模式

本文把docker服务所在的操作系统成为宿主系统, 通过-p标志绑定端口又如下几种方式:

  • 容器端口绑定到宿主系统特定接口的特定端口上
1
-p 127.0.0.1:5000:5000
  • 绑定到宿主系统的随机端口上(49000~49900)
1
-p 127.0.0.1::5000
  • 绑定到宿主系统的所有接口上(0.0.0.0)
1
-p 5000:5000
  • 还可以指定协议(TCP或UDP,等)
1
-p 127.0.0.1:5000:5000/udp
  • -p 标记可以使用多次,同时绑定多个端口
1
-p 127.0.0.1:5000:5000 -p 127.0.0.1:5001:5001

容器链接

网络端口不是容器之间相互链接的唯一方式, Docker 还有一个链接系统能够把多个容器链接到一起.通过Linking, 容器之间能够相互发现,并能够安全地传输信息. 当创建Linking时,实际上是在容器和目标容器之间建立了一根管道(Conduit). 要创建Linking,需要使用--link标志, 首先创建一个新容器,其中包含我们要访问的数据库:

从镜像training/postgres创建一个叫做db的容器, 其中包含PostgreSQL数据库.

1
docker run -d --name db training/postgres:latest

创建一个web容器,并链接到db容器

1
docker run -d -P --name web --link db:db training/webapp python app.py

要建立容器之间的链接,必须在启动时通过参数--name $container_name给容器命名,例如:

1
docker run -d -P --name web training/webapp python app.py

--link 标志的形式如下:

1
--link name:alias

其中 name 为被链接的容器名称 alias 为链接的别名

我们启动db容器的时候并没有指定-P-p参数,在这个例子中,web容器作为接受者(recipient)把自己的信息暴露给作为source(源)db, Docker在两个容器之间创建了一个安全的隧道,这是链接的巨大优势, 通过连接,我们不需要向外部网络暴露端口.

Docker通过两种方式把链接暴露给recipient(接受者)容器:

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

Docker设置了一堆环境变量, 可以使用env命令列出指定容器的环境变量:

1
root@localhost:~# sudo docker run --rm --name web2 --link db:db training/webapp env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=7f3a2434b08a
DB_PORT=tcp://172.17.0.21:5432
DB_PORT_5432_TCP=tcp://172.17.0.21:5432
DB_PORT_5432_TCP_ADDR=172.17.0.21
DB_PORT_5432_TCP_PORT=5432
DB_PORT_5432_TCP_PROTO=tcp
DB_NAME=/web2/db
DB_ENV_PG_VERSION=9.3
HOME=/