代码级干货 | 进阶Docker 1.12,全新的分布式应用捆绑包

在Docker 1.12版本中,全新的Swarm捆绑包相较于原有编排及调度机制做出了巨大改进。它不再需要运行一组独立的Swarm容器,这部分容器已经被直接捆绑在Docker Engine当中,故障转移策略更为可靠,服务发现机制实现内置,新的网络功能极为顺畅……看起来很棒是不是? 数人云这就带大家一起去探索一二。

在之前的文章中,我们已经介绍了如何利用命令在Swarm集群当中运行Docker服务。相信Docker Compose所实现的简化效果会令大家印象深刻。相较于强行记忆命令后的全部参考以实现服务运行,现在大家只需要将一切设置指定为Docker Compose文件,而后利用简单的docker-compose up –d命令运行容器即可。毫无疑问,这样的处理方式比在docker service create命令之后添加一大堆参数要简单得多。

而在上手新的Swarm时,我个人的第一印象是“太棒了”,接下来则是“我不想硬背与服务相关的一大堆参数”。Compose文件的回归简直令人热泪盈眶。

新版本的一大显著变化在于,容器管理已经由客户端(Docker Compose)转移至服务器端(Docker Serivce)。如此一来,Docker Compose就显得有些过时了(至少在使用由Docker Serivce部署的容器时是如此)。当然,大家还是可以在单一服务器环境下利用Docker Compose运行容器,但其作用恐怕也就仅限于此了。因此,我们到底要如何处理已经创建完成的这一大堆docker-compose.yml文件?

好消息是,我们可以分布式应用捆绑包或者简称dab文件替代docker service命令行中的参数。坏消息是……咱们还是先探索好的这部分内容吧。

我们这里首先构建一套由Docker设备构成的演示Swarm集群。

环境设置

在本示例中,我们假定大家已经拥有包含有Docker Engine v1.12+的Docker Machine v0.8+版本。最简单的获取方式就是使用Docker Toolbox。

如果大家身为Windows用户,则可利用Git Bash(同样通过Docker Toolbox进行安装)运行全部示例。

这里将不再赘述环境的设置步骤。我们将创建三个节点,并利用其构建起一套Swarm集群。

docker-machine create -d virtualbox node-1 docker-machine create -d virtualbox node-2 docker-machine create -d virtualbox node-3 eval $(docker-machine env node-1) docker swarm init \ --advertise-addr $(docker-machine ip node-1) \ --listen-addr $(docker-machine ip node-1):2377 TOKEN=$(docker swarm join-token -q worker) eval $(docker-machine env node-2) docker swarm join --token $TOKEN $(docker-machine ip node-1):2377 eval $(docker-machine env node-3) docker swarm join --token $TOKEN $(docker-machine ip node-1):2377 包含三个节点的Docker Swarm集群

现在我们已经拥有了Swarm集群,下面利用一个dab文件部署一项服务。

利用分布式应用捆绑包(简称DAB)部署服务

相较于利用大量参数创建网络及Docker服务,这里我们选择使用一个dab文件。大家可以将其作为Swarm当中的Docker Compose。至于Swarm,我指的是docker swarm、docker service以及其它来自1.12+版本的新机制(而非以往作为独立容器运行的Swarm)。

相较于指定新格式的具体细节以建立服务,这里我们直接使用docker-compose.yml文件完成设置。

让我们首先检查演示服务的代码。

git clone https://github.com/vfarcic/go-demo.git cd go-demo cat docker-compose.yml

最后一项命令会输出Docker Compose项目定义,其具体内容如下。

version: '2' services: app: image: vfarcic/go-demo ports: - 8080 db: image: mongo

如大家所见,这个项目非常简单。其中只包含两项服务,app服务为后端并公开一个API,其利用第二项服务(db)进行数据存储与检索。app服务公开端口8080,并将其作为API的入口点。

将此Docker Compose定义转化为捆绑包需要进行两步操作。首先,我们需要提取相关镜像。该bundle的创建会首先进行镜像评估,而后将docker-compose.yml文件的内容与之相合,最终输出为dab文件。

下面进行尝试。

eval $(docker-machine env node-1) docker-compose pull
docker-compose bundle

现在这一流程已经完成,看看结果如何。 cat godemo.dab
其输出结果如下所示: { "Services": { "app": { "Image": "vfarcic/go-demo@sha256:f7436796b1cd6812ba63ea82c6523a5164ae7f8a3c05daa9e4ac4bd78341d709", "Networks": [ "default" ], "Ports": [ { "Port": 8080, "Protocol": "tcp" } ] }, "db": { "Image": "mongo@sha256:e599c71179c2bbe0eab56a7809d4a8d42ddcb625b32a7a665dc35bf5d3b0f7c4", "Networks": [ "default" ] } }, "Version": "0.1" } 我们刚刚创建的godemo.dab文件非常简单。其中包含的两项服务与docker-compose.yml文件相匹配。每项服务都指定了与提取的哈希值相符合的镜像。镜像部分之后为默认网络,包括相关服务以及需要开启的端口。

这部分输出结果中至少包含两个问题。第一,我们不需要开启任何端口。相反,我们应当使用反向代理将全部请求重新定向至该服务。新的Docker Swarm网络功能已经整合了一项代理,我们应当直接加以利用。

第二个问题在于,我们并没有指定任何约束条件。将不受约束的服务部署至集群当中无疑会引发严重的问题。

大家可以参阅此docker-compose-swarm.yml文件以获取一项更好但同样非常简单的Compose定义。其内容如下所示:

version: '2' services:
app: image: vfarcic/go-demo mem_limit: 250m db: image: mongo mem_limit: 500m

可以看到,我们移除了端口部分内容并添加了一项mem_limit约束。这个Compose文件仍然非常简单。

下面创建新的捆绑包输出结果。

docker-compose -f docker-compose-swarm.yml bundle

运行bundle命令后的输出结果如下所示:

WARNING: Unsupported key 'mem_limit' in services.app - ignoring WARNING: Unsupported key 'mem_limit' in services.db - ignoring
Wrote bundle to godemo.dab

现在我们来谈第一条坏消息。目前的bundle格式还存在诸多局限。我们可以利用其处理非常简单的场景,然而一旦指定任何复杂的内容,系统即会给出警告。在本示例中,我们忽略内存限制警告。

现在我们暂时不理这一限制警告,尝试部署刚刚创建的新捆绑包。

docker deploy godemo

运行deploy命令后的输出结果如下所示:

Loading bundle from godemo.dab Creating network godemo_default
Creating service godemo_app
Creating service godemo_db

现在网络与服务都已经创建完成。我们可以列出全部服务进行确认。

docker stack ps godemo

可以看到由两项服务构成的堆栈,每项服务都被部署在我们的这套三节点集群中的某个位置,而且当前状态为running。如果显示的状态与此不符,则请等待一会儿让容器完成提取,再重新运行此命令。

不过其中仍存在功能缺失的问题。我们的内存限制被忽略了,而且还没有创建外部网络proxy并将app服务附加至该代理处。

要解决这个问题,我们可以执行service update命令。举例来说,我们可以手动创建proxy网络并将其中添加容器。我们也可以使用service update命令设置内存限制。然而,如果我们进行这样的操作,那么一开始就不应该使用捆绑包机制。

接下来该做些什么?

在大家决定放弃bundle之前,请注意这套方案尚处于实验阶段。本篇教程只是为了让大家先尝尝鲜。我们预计其未来将迎来巨大改进,且能够全面支持Swarm提供的各项功能。

现在的问题是,我们当前能够做些什么。这里建议大家选择以下几种作法:其一,等待bundle完成实验阶段并支持Docker Swarm能够提供的全部功能; 其二,使用Whaleprint项目,其基本上相当于dab文件与其它功能(例如约束)以及Terraform方案的结合体。此项目很有前途,不过与bundle一样,其同样处于起步阶段。

希望本篇文章能够帮助大家了解全新Swarm的发展方向。目前bundle还在开发当中,我们预计其未来将成为一种向集群部署服务的可靠备选方案。总而言之,立足于当下期待未来才是最重要的,千万别被其简陋的现状所吓退。

因此,我建议大家对颁式应用捆绑包加以关注并静待其发展成熟。在此期间,通过命令或者尝试Wahleprint项目则是最好的选择。

​ PS,数人云新一期的活动报名开始啦,听大牛们谈谈容器的情怀,如何助力敏捷开发,高效运维,让产品迭代力MAX!点击下方链接快快报名吧!
数人云Meetup|容器助力产品迭代力MAX