如何跨主机连接Docker服务?

Docker 允许来自多个容器的服务器通过链接和服务发现相互连接 。 但是,从我所看到的这个服务发现是主机本地。 我想实现使用其他服务器上托pipe的服务的服务。

在Docker中有几种解决这个问题的方法,比如CoreOS的jumpers ,主机代理到另一台机器的主机本地服务,以及一大堆pipe理Docker部署的github项目,这些项目似乎试图支持这种使用方式,案件。

鉴于发展的速度,很难遵循当前的最佳做法。 因此,我的问题基本上是:1)目前在Docker中跨主机连接的主要方法是什么(如果有的话),2)有没有计划直接在Docker系统中支持这个function?

更新

Docker最近宣布了一个名为Swarm for Docker Orchestration的新工具。

Swarm允许你“连接”多个docker守护进程:你首先创build一个swarm,在一台机器上启动一个swarm manager,并让docker守护进程使用swarm的标识符“join”swarm manager。 docker客户端连接到群pipe理器,就好像它是一个普通的docker服务器。

当一个以Swarm开始的容器时,它将被自动分配给一个空闲节点,以满足已定义的任何约束条件。 以下示例来自博客文章:

 $ docker run -d -P -e constraint:storage=ssd mysql 

受支持的约束之一是"node" ,它允许您将容器固定到特定的主机名。 群体还解决跨节点的链接。

在我的testing中,我得到了一个印象,即Swarm还没有在固定的位置很好地处理卷(或者至less将它们连接起来不是很直观),所以这是要记住的。

Swarm现在处于testing阶段。


直到最近, 大使模式才是远程主机服务发现的唯一Docker本地方法。 这个模式仍然可以使用,并且不需要普通的Docker以外的任何魔法,因为这个模式只包含一个或多个充当代理的附加容器。

此外,有几个第三方扩展使Docker集群function。 第三方解决scheme包括:

  • 在两台主机上连接Docker网桥,存在轻量级和各种解决scheme,但通常还有一些注意事项
  • 基于DNS的发现,例如使用skydock和SkyDNS
  • Dockerpipe理工具,如Shipyard和Docker业务stream程工具。 看到这个问题的广泛的列表: 如何在生产中扩展Docker容器

更新3

Libswarm已经更名为swarm ,现在是一个单独的应用程序。

这里是github页面演示作为一个起点:

 # create a cluster $ swarm create 6856663cdefdec325839a4b7e1de38e8 # on each of your nodes, start the swarm agent # <node_ip> doesn't have to be public (eg. 192.168.0.X), # as long as the other nodes can reach it, it is fine. $ swarm join --token=6856663cdefdec325839a4b7e1de38e8 --addr=<node_ip:2375> # start the manager on any machine or your laptop $ swarm manage --token=6856663cdefdec325839a4b7e1de38e8 --addr=<swarm_ip:swarm_port> # use the regular docker cli $ docker -H <swarm_ip:swarm_port> info $ docker -H <swarm_ip:swarm_port> run ... $ docker -H <swarm_ip:swarm_port> ps $ docker -H <swarm_ip:swarm_port> logs ... ... # list nodes in your cluster $ swarm list --token=6856663cdefdec325839a4b7e1de38e8 http://<node_ip:2375> 

更新2

官方的方法是现在使用libswarm 在这里看到一个演示

UPDATE

Docker中使用相同方法的openvswitch主机通信有一个很好的要点 。

为了允许服务发现,有一个基于DNS的有趣方法称为skydock 。

还有一个截屏 。


这也是一个很好的文章使用相同的难题,但也添加了顶部的vlans:

http://fbevmware.blogspot.it/2013/12/coupling-docker-and-open-vswitch.html

修补与解决scheme的健壮性无关。 Docker实际上只是Linux容器上的一种DSL,这两篇文章中的解决scheme都只是绕过一些Docker的自动设置,直接回退到Linux容器。

所以你可以安全地使用这些解决scheme,一旦Docker实现它,等待能够以更简单的方式来完成。

Weave是一种新的Docker虚拟networking技术,充当TCP / UDP上的虚拟以太网交换机 – 您只需要在主机上运行Weave的Docker容器。

这里有趣的是

  • 在虚拟networking中使用静态IP /主机名而不是链接
  • 主机不需要完全的连通性,基于可用的对等体形成网状,并且分组将被路由多跳到他们需要去的地方

这导致像有趣的情况

  • 在WAN上创build一个虚拟networking,Docker容器都不会知道或关心他们所在的实际networking
  • 将您的容器移动到不同的物理泊坞窗主机,Weave将相应地检测到同级

例如,有一个关于如何在笔记本电脑上创build多节点Cassandra集群的示例指南 ,以及每个主机有两个命令的云(EC2)主机。 我使用AWS CloudFormation创build了一个CoreOS集群,在每个/ home / core上安装了weave,还有我的笔记本电脑vagrant docker VM,并在一个小时之内build立了一个集群。 我的笔记本电脑被防火墙挡住了,但编织似乎没有问题,它只是连接到它的EC2同行。

以下文章很好地描述了如何在多个主机上连接Docker容器: http : //goldmann.pl/blog/2014/01/21/connecting-docker-containers-on-multiple-hosts/

可以使用Open vSwitch或Tinc将多个Docker子网桥接在一起。 我已经准备好要显示如何去做:

  • 打开vSwitch: https : //gist.github.com/noteed/8656989
  • Tinc: https ://gist.github.com/noteed/11031504

我看到使用这个解决scheme而不是--link选项和大使模式的--link是,我发现它更透明:不需要额外的容器,更重要的是,不需要暴露主机上的端口。 实际上,在Docker获得关于多主机(或多守护进程)设置的更好的故事之前,我认为--link选项是暂时的黑客攻击。

注:我知道还有另一个答案指向我的第一个Gist,但我没有足够的业力来编辑或评论这个答案。

更新

Docker 1.12包含了所谓的swarm模式,并增加了一个service抽象。 对于每个用例,它们可能都不够成熟,但是我build议你让它们保持观察。 群体模式至less有助于多主机设置,这不一定使连接更容易。 Docker内部的DNS服务器(从1.11版本开始)应该可以帮助您访问容器名称(如果它们是众所周知的) – 这意味着在Swarm上下文中生成的名称不会那么容易解决。


随着Docker 1.9的发布,你将得到build立在多主机networking 。 他们还提供了一个示例脚本来轻松configuration工作集群。

您将需要一个K / V存储(例如Consul),允许在每个主机上的不同Docker引擎之间共享状态。 每个Docker引擎都需要configuration该K / V存储,然后可以使用Swarm连接主机。

然后你创build一个像这样的新的覆盖networking:

 $ docker network create --driver overlay my-network 

容器现在可以用networking名称作为运行参数运行:

 $ docker run -itd --net=my-network busybox 

它们也可以在运行时连接到networking上:

 $ docker network connect my-network my-container 

文档中提供了更多详细信息。

如上所述, Weave无疑是将Docker容器连接到主机的可行解决scheme。 根据我自己的经验,设置它是相当直接的。 它现在也有DNS服务 ,您可以通过其DNS名称来解决容器的问题。

另一方面,CoreOS的Flannel和Juniper的Opencontrail将主机上的容器连接起来。

似乎docker群1.14允许您:

  • 使用--hostname标签将主机名分配给容器,但是我一直无法使其工作,容器无法通过分配的主机名相互ping通。

  • 将服务分配给机器使用--constraint 'node.hostname == <host>'