1. 运行一个容器,通过–name指定一个便于影象的名字,这个容器被称为source container,也便是要连接的容器
$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=server -d mysql
上面通过通报环境变量MYSQL_ROOT_PASSWORD=server,来设置MySQL做事的密码为server
2. 运行其余一个容器,并link到上面启动的容器,这个容器被称为received container
$ docker run --name nginx --link mysql:aliasmysql -d nginx
上面通过–link连接名为db的容器,并为其设置了别名aliasmysql。
完成了上面的两个步骤后,在nginx的容器中就可以利用db或者aliasmysql作为连接地址来连接MySQL做事,纵然容看重启了,地址发生了变革,不会影响两个容器之间的连接。
二、link机制的连接信息通报
虽然通过利用link机制nginx可以和MySQL进行通信了,但是如何知道Mysql的端口是多少呢?虽然说是固定的是3306,但是也不用除变动端口号的问题,并且对应一些非固定端口的运用来说,只要连接的容器的端口信息也是尤为主要的,link机制通过环境变量的办法供应了这些信息,除此之外像mysql的密码这些信息也会通过环境变量供应,docker将source container中定义的环境变量全部导入到received container中,在received container中可以通过环境变量来获取连接信息下面是mysql中供应的环境变量:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=2ba8f2a337acMYSQL_ROOT_PASSWORD=serverGOSU_VERSION=1.7MYSQL_MAJOR=5.7MYSQL_VERSION=5.7.21-1debian8HOME=/root
注: 利用docker exec mysql env命令来得到上面的结果。
下面我们来看看在nginx这个容器中,这些变量是如何被导入的。
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=754d18a1535dALIASMYSQL_PORT=tcp://172.17.0.3:3306ALIASMYSQL_PORT_3306_TCP=tcp://172.17.0.3:3306ALIASMYSQL_PORT_3306_TCP_ADDR=172.17.0.3ALIASMYSQL_PORT_3306_TCP_PORT=3306ALIASMYSQL_PORT_3306_TCP_PROTO=tcpALIASMYSQL_NAME=/nginx/aliasmysqlALIASMYSQL_ENV_MYSQL_ROOT_PASSWORD=serverALIASMYSQL_ENV_GOSU_VERSION=1.7ALIASMYSQL_ENV_MYSQL_MAJOR=5.7ALIASMYSQL_ENV_MYSQL_VERSION=5.7.21-1debian8NGINX_VERSION=1.13.8-1~stretchNJS_VERSION=1.13.8.0.1.15-1~stretchHOME=/root
上面的变量被分成了五个部分:
第一个部分是nginx容器自身供应的一些环境变量,如NGINX_VERSION,HOSTNAME,HOME,PATH等。第二个部分则是ALIASMYSQL_ENV开头的变量,这些都是从source container中导入的,变量来源于Dockerfile中利用ENV命令定义的变量,或者是docker run的时候通过-e添加的环境变量。第三个部分是ALIASMYSQL_NAME这个变量,这变量记录了link的两个容器的组合,这里便是/nginx/aliasmysql。第四个部分便是ALIASMYSQL_PORT开头的一系列变量,这些变量会有分组,每组变量的命名格式如下<alias>_PORT_<port>_<protocol><alias>_PORT_<port>_<protocol>_PORT<alias>_PORT_<port>_<protocol>_PROTO<alias>_PORT_<port>_<protocol>_ADDR
个中<port>是在Dockerfile中利用EXPOSE导出的端口,还有docker run的时候利用-p导出的端口。<protocol>则是这些端口对应的协议。
第五个部分便是ALIASMYSQL_PORT这个变量,这个变量是EXPOSE导出端口中的第一个端口对应的连接url, 如果有EXPOSE导出的端口,还有docker run -p指定导出的端口,那么通过-p指定的端口是第一个被导出的端口。三、link机制和/etc/hosts利用了link机制后,可以通过指定的名字来和目标容器通信,这实在是通过给/etc/hosts中加入名称和IP的解析关系来实现的,下面是名为nginx的容器中的/etc/hosts信息。
127.0.0.1 localhost::1 localhost ip6-localhost ip6-loopbackfe00::0 ip6-localnetff00::0 ip6-mcastprefixff02::1 ip6-allnodesff02::2 ip6-allrouters172.17.0.3 aliasmysql 2ba8f2a337ac mysql172.17.0.4 754d18a1535d
通过上面的信息可以看出,link机制给received container(这里是名为nginx的容器)添加了一条关于mysql容器的名称解析。有了这个名称解析后就可以不该用ip来和目标容器通信了,除此之外当目标容看重启,docker会卖力更新/etc/hosts文件,因此可以不用担心容看重启后IP地址发生了改变,解析无法生效的问题。但是很不幸的是,环境变量无法更新,上文中提到了link机制会通过环境变量将一些mysql容器的信息导入到nginx容器中,这种导入是一次性的,此后这个容器更新了环境变量的信息是无法在nginx容器中更新的。
四、link机制和网络新特性通过上文中对link机制的先容,可以创造link机制供应了如下几个功能:名称解析、对link的容器可以利用别名、安全的容器间连接通信、环境变量的注入。
对付安全的容器间连接通信,这个须要结合docker daemon的 -icc=false这个选项,默认同一个宿主机上的所有容器可以相互通信,当利用 -icc=false的时候所有容器之间是无法进行相互通信的(详细缘故原由会单独出篇文章剖析),但是利用link机制后,纵然利用了 -icc=false两个容器之间也可以进行基于端口的通信。很不幸的是当docker引入网络新特性后,link机制变的有些多余,但是为了兼容早期版本,–link机制在默认网络上的功能依旧没有发生变革,docker引入网络新特性后,内置了一个DNS Server,但是只有用户创建了自定义网络后,这个DNS Server才会起浸染。在网络新特性为未引入之前,有三种网络,第一种便是docker0这种桥接管集,用的也是最多的,第二个则是复用主机网络,称为HOST网络,第三种便是none网络,只创建了一个空的网络命名空间,没有网络接口,无法和外界通信,可以让利用者自己去构建网络。当网络新特性引入后,有了overlay网络,有了用户自定义网络。用户自定义网络下,用户可以通过docker的network子命令创建一个自定义的桥接管集,这个自定义桥接的网络和默认的docker0桥接管集基本功能都是同等的,只是在这个自定义桥接管集中拥有一些特性,可以替代link机制。这些特性包括如下几个方面:
基于DNS的名称自动解析安全的隔离环境动态的附加或者分开一个网络支持利用–link设置别名在用户自定义网络下,不该用link机制就可以实现名称解析功能了,不再是通过link机制追加名称解析关系到/etc/hosts文件中了。并且在默认的docker0桥接管集和自定义网络下利用link机制的效果是不一样的,在自定义网络中link机制只是卖力设置别名的,不再供应环境变量注入的功能了。自定义网络中同时也供应了 --net-alias功能和link机制供应别名功能是一样的。保留link机制目的是为了兼容。
五、link容器配置调用变量前面我们已经说了,link主机会导入被link主机的环境变量,以供link主机做事的利用。这些被导入的环境变量前缀便是 --link时设置的主机别名,前缀之后的部分都是相同的。以是这些是有规律可循的。既然是Shell环境变量,如果你在link主机中跑的是shell脚本,那么就大略了,直接应用对应的变量即可。如下:
$ mysql -h ${ALIASMYSQL_PORT_3306_TCP_ADDR} -P ${ALIASMYSQL_PORT_3306_TCP_PORT} -uroot -p\"大众${ALIASMYSQL_ENV_MYSQL_ROOT_PASSWORD}\公众
这些变量是默认的,当然你也可以在启动link主机时利用-e传入这些变量,但传入的变量要跟容器中利用的变量约定好。
那么如果不是shell脚本,是php、python、java的配置文件呢,如何利用传入的shell变量?我能想到的办法便是在容器构建时,先实行一个shell脚本,利用一些shell命令(如sed)来更换配置文件中须要传入的参数。然后再启动做事。
六、link机制的缺陷停滞link连接的目标容器,hosts文件并不会更新,只有目标容看重新启动,才会更新hosts文件。容器须要按照link之间的依赖关系依次启动。移除一个link连接的容器,可能会造玉成部系统的link失落效,须要删除并重新建立所有利用–link的容器。如果是新的docker系统,只管即便利用docker的User-defined networks来掌握容器之间的相互通信,同时官方文档也提到 --link可能会在往后的版本中被移除,以是以前利用 --link的系统,如果条件许可,也该当只管即便迁移到networks特性上面来。
篇幅有限,关于docker容器间link通信机制就先容到这啦,希望对大家有点帮助。
后面会分享更多devops内容,感兴趣的朋友可以关注下~