Docker之容器互联


这是一篇关于docker容器之间互联的文章,主要讲解了使用–link连接容器的方式

Docker容器间的互联,意思是一个容器可以使用另一个或多个其他容器提供的功能.比如,一个web应用需要数据库的支持,除了在一个容器内同时运行web应用程序和数据库程序之外,更好的办法是用两个容器.一个运行web应用,另一个专门提供数据库服务.这样不仅方便管理,同时也节省资源,尤其是当同一宿主机下运行了多个需要数据库服务的容器时,我们可以使用一个数据库容器同时向它们提供服务.

上次讲Docker的数据管理时,说道Docker使用卷和卷容器来使两个容器通信,使用的是-v标志和–volumes-from参数,但这种方式最主要的任务是提供数据而不是服务,是为了方便数据迁移和备份.而要提供服务的话,使用的是–link参数.(–link参数是用于同一主机上的两个容器之间的互联,而不同主机的两个容器之间的互联我们以后介绍).

使用–link互联有什么好处呢?如果不使用–link的话,我们要让a容器使用b容器提供的服务,就需要b容器通过EXPOSE指令或-e标志将自己的端口暴露出来供其他的容器访问.举个例子,假设你创建了一个运行mysql服务的容器,要给其他的容器提供数据库服务,就要在创建它的Dockerfile中使用EXPOSE指令打开一个端口:

EXPOSE 3306

而且在运行容器时要使用-p标识将端口暴露出来:

docker run --name mysql -p 3306:3306 -d mysql //或者使用-P

这样其它的容器才能访问到mysql服务.
但这样会使端口保留在外,任何容器甚至其他工具均能访问,这会带来一定的安全问题.

下面结合使用mysql镜像和wordpress镜像搭建wordpress博客看一下–link怎么用.(mysql.wordpress镜像均来自Docker Hub官方镜像)
首先启动mysql容器,使用如下命令:

docker run --name mysql -d mysql

我们给这个mysql容器取名为mysql,这里最好不要使用默认的名字,而是给它取一个好记的名字,名字是容易的唯一标示,这个名字以后要用.

然后我们运行一个wordpress容器,这里运行时需要一些参数.我把官方的说明粘贴在下面:
Docker之容器互联_第1张图片
可以看到使用docker run 运行wordpress时可以通过-e标志指定一些参数,如主机地址,用户名和密码,这里我们都使用默认,你也可以自己设定.
我们通过如下命令启动wordpress:

docker run --name wordpress --link mysql:mysql -p 8080:80 -d wordpress

这里我为运行的容器取名wordpress,由于一个博客是需要提供给外部访问的,所以我们用-p标志将容器的80端口(wordpress默认绑定在80端口上)绑定在了宿主机的8080端口上(你也可以指定其他端口,如12345).这样我们在宿主机浏览器的地址栏输入:localhost:8080就可以看到一个新建的博客了.

最重要的就是–link参数,这也是我们这篇文章的主题,–link的格式为: –link name:alias
其中name是提供服务的容器的名字,这里就是提供mysql服务的mysql容器,alias是连接的别名.

Docker通过两种方式为容器公开连接信息:
- 环境变量
- 更新hosts文件

我们执行如下命令:

docker exec wordpress env

这条命令用docker exec在wordpress中执行了env命令,env用户显示当前容器中定义的环境变量,运行它,我们可以看到如下信息:

chy@chy-station:~$ docker exec wordpress env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=a4d68974e452
MYSQL_PORT=tcp://172.17.0.2:3306
MYSQL_PORT_3306_TCP=tcp://172.17.0.2:3306
MYSQL_PORT_3306_TCP_ADDR=172.17.0.2
MYSQL_PORT_3306_TCP_PORT=3306
MYSQL_PORT_3306_TCP_PROTO=tcp
MYSQL_NAME=/wordpress/mysql
MYSQL_ENV_MYSQL_ROOT_PASSWORD=838566
MYSQL_ENV_MYSQL_MAJOR=5.7
MYSQL_ENV_MYSQL_VERSION=5.7.9-1debian8
PHP_INI_DIR=/usr/local/etc/php
PHP_EXTRA_BUILD_DEPS=apache2-dev
PHP_EXTRA_CONFIGURE_ARGS=--with-apxs2
GPG_KEYS=0BD78B5F97500D450838F95DFE857D9A90D90EC1 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3
PHP_VERSION=5.6.15
WORDPRESS_VERSION=4.3.1
WORDPRESS_SHA1=b2e5652a6d2333cabe7b37459362a3e5b8b66221
HOME=/root

我们看到一系列的以MYSQL_开头的环境变量,这些都与mysql数据库有关,wordpress正是使用这些变量来与mysql服务进行连接.

关于--link时产生的环境变量,以下这些信息你应该知道:

当我们使用--link将source容器连接到target容器时,Docker会在target中生成一些环境变量,也会将source容器中已有的环境变量加入到target中。其中source中已有的环境变量包括:
- Dockerfile中通过ENV指令指定的环境变量;
- 启动source容器时通过-e--env--env-file指定的环境变量。

此外,Docker会在target容器中生成的环境变量包括:
_NAME 变量,其中是连接的别名;
Docker还为source容器中每个暴露(expose)的端口生成一组环境变量,其中每个变量都有以下前缀:
_PORT__
其中是连接的别名,通过--link指定;是要暴露的端口;是UDP或TCP。
使用这个前缀,Docker为每个暴露的端口生成的一组环境变量如下:
- prefix_ADDR:表示source容器的IP地址,例如:WEBDB_PORT_5432_TCP_ADDR=172.17.0.82
- prefix_PORT:表示要暴露的端口号,例如:WEBDB_PORT_5432_TCP_PORT=5432
- prefix_PROTO:表示协议,udptcp,例如:WEBDB_PORT_5432_TCP_PROTO=tcp

如果source容器暴露了多个端口,那么每一个端口都会在target容器中生成一组这样的环境变量。
此外,Docker还会在target容器中生成一个表示URL的环境变量。名字为_PORT,其中是连接的别名,port是source所有暴露端口中值最小的一个,例如:WEBDB_PORT=tcp://172.17.0.82:5432

需要特别指出的是,在重启容器时,容器的IP可能会改变,但Docker默认不会自动更新由--link产生的环境变量。

除此之外,wordpress还需与mysql容器进行通信,这是通过更新/etc/hosts实现的,我们再执行以下命令查看wordpress的hosts文件:

chy@chy-station:~$ docker exec wordpress cat /etc/hosts
172.17.0.3  a4d68974e452
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2  mysql 4964536335b2

其中第一行172.17.0.3是wordpress容器使用的IP地址后面的一串字符是它的主机名称,这是Docker自动生成的.
重点关注最后一行,127.17.0.2是mysql容器的IP地址(可以对mysql容器执行docker inspect命令验证),后面还有mysql的标识.
与环境变量不同,容器重启后,Docker会自动刷新hosts文件,确保其与当前真实IP地址一致。

你可以在新建的博客中进行一些操作,如发篇文章什么的,以确定其功能是否正常.
那么,wordpress究竟有没有连接到数据库呢,产生这样的怀疑是因为,我们好像没有进行什么配置,而通常情况下要搭建博客需要很多配置项,为了验证是否真的连接到了数据库,我们再启动一个mysql容器连接到正在运行的那个mysql容器,使用如下命令:

docker run -it --link mysql:mysql --rm mysql sh -c 'exec mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"$MYSQL_PORT_3306_TCP_PORT" -uroot -p"$MYSQL_ENV_MYSQL_ROOT_PASSWORD"'

可以看到我们使用了一些有关mysql服务参数的环境变量,因为新启动的mysql容器也link到了原来的mysql容器,所以在它内部也有这些环境变量.
这样我们就登录到了给wordpress提供数据库服务的mysql的命令行控制台了,在控制台我们执行show databases;命令,就可以看到有一个名为wordpress的数据库,那就是wordpress容器建立的数据库,说明我们的连接成功了.

mysql> show databases
    -> ;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| wordpress          |
+--------------------+
5 rows in set (0.00 sec)

你可能感兴趣的:(docker)