这是一篇关于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 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容器中生成的环境变量包括:
变量,其中是连接的别名;
Docker还为source容器中每个暴露(expose)的端口生成一组环境变量,其中每个变量都有以下前缀:
其中
是连接的别名,通过--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
:表示协议,udp
或tcp
,例如:WEBDB_PORT_5432_TCP_PROTO=tcp
如果source容器暴露了多个端口,那么每一个端口都会在target容器中生成一组这样的环境变量。
此外,Docker还会在target容器中生成一个表示URL的环境变量。名字为
,其中
是连接的别名,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)