wwwhy76888com理解容器间link通信机制199O8836661

一、什么是docker的link机制?

同一个宿主机上的多个docker容器之间如果想进行通信,可以通过使用容器的ip地址来通信,也可以通过宿主机的ip加上容器暴露出的端口号来通信,前者会导致ip地址的硬编码,不方便迁移,并且容器重启后ip地址会改变,除非使用固定的ip,后者的通信方式比较单一,只能依靠监听在暴露出的端口的进程来进行有限的通信。通过docker的link机制可以通过一个name来和另一个容器通信,link机制方便了容器去发现其它的容器并且可以安全的传递一些连接信息给其它的容器。其使用方式如下:

  1. 运行一个容器,通过–name指定一个便于记忆的名字,这个容器被称为source container,也就是要连接的容器

$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=server -d mysql
上面通过传递环境变量MYSQL_ROOT_PASSWORD=server,来设置MySQL服务的密码为server

  1. 运行另外一个容器,并link到上面启动的容器,这个容器被称为received container

$ docker run --name nginx --link mysql:aliasmysql -d nginx
上面通过–link连接名为db的容器,并为其设置了别名aliasmysql。

完成了上面的两个步骤后,在nginx的容器中就可以使用db或者aliasmysql作为连接地址来连接MySQL服务,即使容器重启了,地址发生了变化,不会影响两个容器之间的连接。

Docker:理解容器间link通信机制
二、link机制的连接信息传递

虽然通过使用link机制nginx可以和MySQL进行通信了,但是如何知道Mysql的端口是多少呢?虽然说是固定的是3306,但是也不排除更改端口号的问题,并且对应一些非固定端口的应用来说,只要连接的容器的端口信息也是尤为重要的,link机制通过环境变量的方式提供了这些信息,除此之外像mysql的密码这些信息也会通过环境变量提供,docker将source container中定义的环境变量全部导入到received container中,在received container中可以通过环境变量来获取连接信息下面是mysql中提供的环境变量:

第一个部分是nginx容器自身提供的一些环境变量,如NGINX_VERSION,HOSTNAME,HOME,PATH等。
第二个部分则是ALIASMYSQL_ENV开头的变量,这些都是从source container中导入的,变量来源于Dockerfile中使用ENV命令定义的变量,或者是docker run的时候通过-e添加的环境变量。
第三个部分是ALIASMYSQL_NAME这个变量,这变量记录了link的两个容器的组合,这里就是/nginx/aliasmysql。
第四个部分就是ALIASMYSQL_PORT开头的一系列变量,这些变量会有分组,每组变量的命名格式如下

其中<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信息。

通过上面的信息可以看出,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机制。这些特性包括如下几个方面:

在用户自定义网络下,不使用link机制就可以实现名称解析功能了,不再是通过link机制追加名称解析关系到/etc/hosts文件中了。并且在默认的docker0桥接网络和自定义网络下使用link机制的效果是不一样的,在自定义网络中link机制只是负责设置别名的,不再提供环境变量注入的功能了。自定义网络中同时也提供了 --net-alias功能和link机制提供别名功能是一样的。保留link机制目的是为了兼容。

五、link容器配置调用变量

前面我们已经说了,link主机会导入被link主机的环境变量,以供link主机服务的使用。这些被导入的环境变量前缀就是 --link时设置的主机别名,前缀之后的部分都是相同的。所以这些是有规律可循的。既然是Shell环境变量,如果你在link主机中跑的是shell脚本,那么就简单了,直接应用对应的变量即可。如下:

这些变量是默认的,当然你也可以在启动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特性上面来。

原文地址:http://blog.51cto.com/14070896/2316060

时间: 2024-11-08 13:01:14

wwwhy76888com理解容器间link通信机制199O8836661的相关文章

从AIDL开始谈Android进程间Binder通信机制

本文首先概述了Android的进程间通信的Binder机制,然后结合一个AIDL的例子,对Binder机制进行了解析. 概述 我们知道,在Android app中的众多activity,service等组件可以运行在同一进程中,也可以运行在不同进程中.当组件运行在同一进程中进行通信就显得比较简单,在之前的Android线程间通信机制中已经讲过了:而当它们运行在不同的进程中时,就需要使用我们本文中所要介绍的Binder机制了. Binder作为一种进程间通信机制,负责提供远程调用的功能(RPC),

Storm集群上的开发 ,Storm的内部原理,storm集群间的通信机制(九)

storm间的worker会互相通信,上一个worker的结果会交给下一个worker进行计算.看图

Nginx之进程间的通信机制(Nginx频道)

1. Nginx 频道 ngx_channel_t 频道是 Nginx master 进程与 worker 进程之间通信的常用工具,它是使用本机套接字实现的,即 socketpair 方法,它用于创建父子进程间使用的套接字. #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int socketpair(int domain, int type, int protocol, int sv[2]); 这个方法

Nginx之进程间的通信机制(信号、信号量、文件锁)

1. 信号 Nginx 在管理 master 进程和 worker 进程时大量使用了信号.Linux 定义的前 31 个信号是最常用的,Nginx 则通过重定义其中一些信号的处理方法来使用吸纳后,如接收到 SIGUSR1 信号就意味着需要重新打开文件. 使用信号时 Nginx 定义了一个 ngx_signal_t 结构体用于描述接收到的信号时的行为: typedef struct { // 需要处理的信号 int signo; // 信号对应的字符串名称 char *signame; // 这个

深入理解docker的link机制

https://yq.aliyun.com/articles/55912 摘要: 什么是docker的link机制 同一个宿主机上的多个docker容器之间如果想进行通信,可以通过使用容器的ip地址来通信,也可以通过宿主机的ip加上容器暴露出的端口号来通信,前者会导致ip地址的硬编码,不方便迁移,并且容器重启后ip地址会改变,除非使用固定的ip,后者的通信方式比较单一,只能依靠监听在暴露出的端口的进程来进行有限的通信.通过docker的link机制可以通过一个name来和另一 什么是docker

Docker之网络管理(容器间通信的配置)

博文大纲: 一.Bridge模式(同一台Docker服务器上容器间的通信) 二.部署consul服务实现Docker容器跨主机通信 前言: 当你开始大规模使用Docker时,你会发现需要了解很多关于网络的知识.Docker作为目前最火的轻量级容器技术,有很多令人称道的功能,如Docker的镜像管理.然而,Docker同样有着很多不完善的地方,网络方面就是Docker比较薄弱的部分.因此,我们有必要深入了解Docker的网络知识,以满足更高的网络需求.本文首先介绍了Docker自身的4种网络工作方

Docker容器学习梳理--容器间网络通信设置(Pipework和Open vSwitch)

自从Docker容器出现以来,容器的网络通信就一直是被关注的焦点,也是生产环境的迫切需求.容器的网络通信又可以分为两大方面:单主机容器上的相互通信,和跨主机的容器相互通信.下面将分别针对这两方面,对容器的通信原理进行简单的分析,帮助大家更好地使用docker.前面已经在Docker容器学习梳理--基础知识(2)这一篇中详细介绍了Docker的网络配置以及pipework工具. docker单主机容器通信 基于对net namespace的控制,docker可以为在容器创建隔离的网络环境,在隔离的

Docker &amp; ASP.NET Core (4):容器间的连接

原文:Docker & ASP.NET Core (4):容器间的连接 第一篇:把代码连接到容器 第二篇:定制Docker镜像 第三篇:发布镜像 Docker容器间的连接 Docker提供了两种方式可以用来做容器间的连接/通信: Legacy Linking:这种方式使用容器名进行连接,实际上它创建了一个桥接的网络,在这个网络里,容器间可以进行通信. 把容器添加到桥接网络:这种方式是创建了一个自定义的桥接网络,它的类型是isolated network(隔离网络),只有在这个网络里的容器才能互相

TensorFlow中的通信机制——Rendezvous(一)本地传输

背景 [作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] 在TensorFlow源码中我们经常能看到一个奇怪的词--Rendezvous.如果从仔细统计该单词出现的频率和模块,你会发现无论在单机还是分布式,无论在core目录还是contrib目录都存在它的身影,所涉及的模块非常多.Rendezvous是一个法语单词,发音也比较特殊,一般直译为"约会.相会.会和",而在TensorFlow中,Rendezvous是用来完成消