敏捷开发理念已经盛行多年,如今越来越多的企业开始拥抱以人为中心、迭代、循序渐进的开发模式。在这一趋势下引入Docker,一个直观的想法是:借助其虚拟化能力,为开发团队打造一套可复用的开发环境,并通过Image分发给所有项目成员,从而简化环境搭建流程。这个想法听起来很理想,但事实上,在Docker出现之前,类似Vagrant这样的工具已经能够实现开发环境的分发。因此,如果仅仅是为了解决环境搭建问题,Docker的优势并不显著。可以说,Docker真正发挥威力的场景,其实是在简化CI(持续集成)和CD(持续交付)的构建流程,让开发者能够将精力集中在核心任务——编写代码上。
每个企业都有其独特的技术栈,我们需要结合实际情况不断优化构建流程。既然要迈出第一步,就必须先绘制清晰的蓝图,做到心中有数,后续工作才能顺利推进。

上图所示的时序图,基本概括了当前敏捷开发流程的各个环节。基于这一蓝图框架,接下来我们重点探讨将Docker引入每个环节时,有哪些实践经验可供借鉴,以及哪些常见陷阱需要规避。
2. 创建持续发布的团队
开发团队在引入Docker时,面临的最大挑战是没有现成的行业标准可供遵循。大家口号响亮,动辄提及“最佳实践”,结果却引入了各种工具链,反而失去了重点。在Docker选型上,仅学习工具本身就已经耗费了大量时间,根本没有精力思考如何利用合适工具组建一个能够持续交付产品的团队。针对这种情况,一个行之有效的评判标准就是“简单易用”,以此作为Docker技术选型的参考准则是明智的。
团队引入Docker时,首先要解决的是让成员尽快熟悉Docker命令行操作。当大家掌握基本操作后,接下来需要处理几个关键问题:
1)Base Image的选取(例如phusion-baseimage)
2)配置管理Docker镜像的工具(例如Ansible、Chef、Puppet)
3)Host主机系统的选择(例如CoreOS、Atomic、Ubuntu)
Base Image包含操作系统命令行最小集及必要库,一旦确定,所有应用都必须基于它构建镜像。Ubuntu是官方默认版本,上手最简单,但系统本身未做特别优化。如果需要更精简或更安全的方案,可以考虑第三方打磨过的版本,比如phusion-baseimage。如果选择RHEL、CentOS分支的Base Image,需要注意它自带的SELinux安全框架、块级存储文件系统devicemapper等技术,与Ubuntu分支不能通用。不同操作系统分支的裁剪方法也完全不同,因此选型时必须慎重。
配置管理Docker镜像的工具,主要用于基于Dockerfile创建Image时的配置管理。选择策略很简单:结合团队现状,挑选大家最熟悉的通用工具。Ansible作为后起之秀,使用体验非常简洁,值得推荐。
Host主机系统是Docker后台进程的运行环境。从开发角度看,它本质上就是一台单机OS——只不过我们只需要在上面运行Docker后台进程和集群工具,所以自然是越轻量越好。推荐关注CoreOS,这是当前开销最小的主机系统。此外,红帽开源的Atomic主机系统也不错,拥有基于Fedora、CentOS、RHEL多个版本可供选择。当然,如果团队有足够实力,也可以选择最小化安装操作系统,自行定制Host系统。
3. 持续集成的构建系统
当开发团队将代码提交到Git仓库的那一刻,相信每个人都希望有个系统能自动帮助我们把应用部署到服务器上,省去不必要的人工操作。然而,复杂的应用部署场景使得这一愿望实现起来并不简单。
首先,我们需要一个支持Docker的构建系统,这里推荐Jenkins。它最大的特点是开源、可定制、使用简单,还能方便地安装各种第三方插件,快速集成其他应用。通过Jenkins的Job触发机制,我们可以创建各种类型的集成Job用例。但如果缺乏统一标准,Job用例会越来越混乱,管理和维护都会变得困难,团队也难以充分利用集成系统的优势。这显然不是我们期望的结果。
针对这一问题,敏捷实践提出了一个非常实用的概念:持续交付的DeploymentPipeline(管道部署)。借助Docker技术,这个概念实施起来会变得非常直观。Jenkins的管道部署将部署流程形象化为一个长长的管道,每隔一小段就有一个节点——也就是Job——必须完成后才能进入下一个环节。形式如下所示:

大家看上图,每一块面板在引入Docker之后,都可以利用Docker将任务模块化,做成有针对性的Image来运行特定任务。而每个任务Image的创建,又可以在开发者自己的环境中完成,类似的场景可以参考下图:
这样,使用Docker之后,任务的模块化就自然而然地被定义出来了。通过管道图,可以清晰看到每一步的执行时间。开发者完全可以根据任务需求,为每个任务制定严格的性能标准,作为后续测试的参考基础。
4. 最佳的发布环境
应用通过测试后,就该发布到测试环境和生产环境了。在这个阶段,如何更合理地使用Docker又是一个难点——开发团队需要打造一个可伸缩、可扩展的分发环境。说白了,这个环境就是基于Docker的私有云,更进一步,我们甚至希望它能提供API接口,成为PaaS云服务。为了构建这样的PaaS服务,这里推荐几款业内比较成熟的开源工具,可以作为参考。
1) Apache Mesos + Marathon
Apache Mesos是一套资源管理调度集群系统,由Twitter发起并开源,在生产环境中可用来实现应用集群。在集群里,我们可以使用Zookeeper开启3个Mesos master服务,它们通过Zookeeper交换信息后选出Leader,其他两台Sla ve Mesos Master上的请求会自动转发到Leader。Mesos sla ve服务器启动后,会把内存、存储空间和CPU资源信息上报给Mesos master。需要注意的是,Mesos本身是一个框架,设计初衷是用来执行Job做数据分析的,它不能直接运行类似Web服务Nginx这种长时间运行的服务。因此,我们需要借助Marathon来弥补这一短板。Marathon提供了自己的REST API,我们可以创建一个配置文件Docker.json:
{
"container": {
"type": "DOCKER",
"docker": {
"image": "libmesos/ubuntu"
}
},
"id": "ubuntu",
"instances": "1",
"cpus": "0.5",
"mem": "512",
"uris": [],
"cmd": "while sleep 10; do date -u +%T; done"
}
然后通过调用
curl -X POST -H "Content-Type: application/json" https://:8080/v2/apps -d@Docker.json
就可以在Mesos集群上创建一个Web服务。具体案例可参考Marathon的官方文档。

2) Google Kubernetes
Google推出的容器集群管理工具,它提出了两个核心概念:
- Pods:每个Pod是一个容器的集合,部署在同一台主机上,共享IP地址和存储空间。例如Apache和Redis这样的应用,就可以分成一组容器集合。
- Labels:提供服务标签,方便Pod容器之间的调用协作。
通过官方架构设计文档,可以详细了解每个组件的设计思想。值得一提的是,这是目前业界唯一一个在生产环境部署经验基础上推出的开源容器方案。可以预见,它未来很可能成为容器管理系统的行业参考标准。

3) Panamax
在集群管理工具层出不穷的今天,单机Docker容器的管理同样是个不可忽视的问题。由于Docker占用内存小,在一台单机上部署成百上千个容器也毫不稀奇。Panamax正是为解决这一问题而生——它提供人性化的Web管理界面,安装软件、部署服务变得非常简单。它还提供丰富的容器模板,使得在线创建服务成为可能。举个例子,你可以在DigitalOcean申请一台主机,安装Panamax并启动为后台服务,然后通过Panamax Web界面一键安装Nginx、Mysql、Redis等服务镜像,快速搭建生产环境。整个过程都在Web界面上完成,开发者只需要专注于开发本身。

5. 结论
Docker的集成部署方案,说到底是一套灵活、简单的工具组合。它克服了之前集群工具复杂、难用的困境,用统一的Docker应用容器概念来部署软件。通过引入Docker技术,开发团队在面对复杂的生产环境时,完全可以结合自身的实际情况,定制出最适合自身基础架构的配套软件部署方案。
