Docker 源于 2013 年成立的一个开源项目,在短短的两年时间里 Docker 镜像的下载量已达到 1 亿次以上。做为当今最热门的云计算技术,Docker 将 “集装箱化思维”运用在了软件“运输”上。我们可以将 Docker 看作是用代码编写出来的国际集装箱,它可以把任何应用及相关依赖项打包成一个轻量、可移植、自包涵式的容器。众多的软件技术人员都为 Docker 此类容器技术的产生和应用前景而感到兴奋。在很多人看来,Docker 将改变人们构建,部署和发布软件的方式。
Docker 是一个开放平台,旨在为开发人员和运维人员提供一种新的方式来构建,传输和运行分布式应用。Docker 忽略开发,测试以及生产环境间的差别,使得开发人员能将各组件快速的组装成应用镜像,从而运维人员能够快速的装配应用,将其完全一致地运行在笔记本,数据中心的虚拟环境,甚至任何云上。
关于 Docker 和虚拟机之间的区别,这里不再赘述。我们可以来看看是什么样的特性使得 Docker 如此受欢迎。
使用 Docker,开发人员可以用任何语言,采用任何工具链构建任何应用,完全支持持续集成和持续发布,从开发笔记本,经过自动化测试到生产环境,不需要任何修改就可以快速构建高质量的应用,做弹性伸缩。
支持在不同云上运行完全相同的应用,并且不和任何云绑定,可作为混合云之间的代理
容器技术使得 CPU,内存和存储等计算资源的使用率更高。支持在任何基础架构上更快更可靠的部署和运行任何应用。
在本文中,我们将以一个名为 JKE Banking(JKE)的典型 J2EE 应用为例,来说明如何做 Docker 应用的持续发布。此应用包括两个基本部署组件,网页逻辑组件(jke-web)和数据组件 (jke-db),分别运行在 jetty 应用服务器和 mysql 数据库中。
注:JKE Docker 应用示例相关代码可以从 github 项目中获取
首先我们介绍如何将 JKE 两个组件的代码封装在两个 Docker 镜像中,然后再看看如何利用包含代码的 Docker 镜像来部署一个 JKE 应用环境。整个过程中,我们会用到两个公共的 Docker 基础镜像,java 和 mysql。
对于网页逻辑组件 jke-web,我们从应用源代码生成一个带有 jetty 服务器的 zip 包,并编写 jke-web 组件 Dockerfile 如下:
FROM java:7 # Install jke.zip COPY jke.zip /opt/jke/ RUN unzip /opt/jke/jke*.zip RUN chmod u+x *.sh CMD ./jke.server.linux.sh restart && tail -F /var/log/faillog
运行 build 命令生成新的 jke-web
镜像
sudo docker build -t jke-web .
对于数据组件 jke-db,我们将数据库初始化脚本放入 mysql 基础镜像中。
jke-db 的 Dockerfile:
FROM mysql # Run SQL COPY init.sql ./ CMD mysql –hmysql-server -uroot –ppassword < init.sql
运行 build 命令生成新的 jke-db
镜像
sudo docker build -t jke-db.
运行 JKE 应用,需要依次运行命令启动三个容器,第一个容器运行 mysql 服务器,第二个容器连接数据库,运行数据库初始化脚本。第三个容器运行 JKE 的主程序,并连接至服务器(在 jke-web 组件的数据库配置文件 JKEDB.properties 中,数据库 hostname 已被设置为 mysql-server)。至此,应用就可以在 http://<docker-hostserver>:8080 端口被访问了。
sudo docker run --name mysql -e MYSQL_ROOT_PASSWORD=password -d mysql sudo docker run --link mysql:mysql-server –d jke-db sudo docker run --link mysql:mysql-server –p 8080:8080 -d jke-web
图 1.JKE 应用-运行在 Docker 容器中
我们需要搭建一个私有的 Docker 镜像仓库,用来存放不同版本的应用组件 Docker 镜像,供开发人员和测试人员上传和下载应用组件镜像,快速搭建应用测试环境和标记状态。
在 Docker 的 1.6 以上的新版本中,只要运行一个 Docker 镜像就能完成私有仓库的搭建,非常方便。
sudo docker run -d -p 5000:5000 registry
接着我们将构建好的最新版本的 jke-web 和 jke-db 组件镜像上传到私有仓库中。
sudo docker tag jke-web:1.1 192.168.27.100:5000/jke-web:1.1 sudo docker push 192.168.27.100:5000/jke-web:1.1 sudo docker tag jke-db:1.1 192.168.27.100:5000/jke-db:1.1 sudo docker push 192.168.27.100:5000/jke-db:1.1
然后我们就可以在局域网内访问和下载这些镜像版本了。比如我们可以直接访问下面的 URL 来查看镜像和版本信息。注:192.168.27.100 为私有 Docker 镜像仓库服务器的 IP 地址。
http://192.168.27.100:5000/v1/search
http://192.168.27.100:5000/v1/repositories/jke-web/tags
回页首
在建立由多套环境构成的 DevOps 交付管道时,我们使用了 IBM UrbanCode Deploy(UCD)。应用部署自动化工具 UCD 提供了一套框架,可以方便的管理 Docker 应用交付涉及到的多套环境。它可以帮助我们集中地部署和管理应用的开发和各种测试环境,并提供了针对 Docker 的插件,来支持在不同的环境中,实时地获取最新版本的 Docker 镜像,自动运行应用并且执行相应的测试套件。
在传统应用的持续交付中,我们关注的是应用部署包的生成,以及部署包在各个环境之间的推送,最终可以在生产环境上部署运行。而在 Docker 应用的持续交付中,我们将关注包含了应用二进制代码的 Docker 镜像的生成以及镜像在各个环境之间的推送,最终在生产环境中以容器的方式无差别的运行。从传统应用到 Docker 应用,变的是承载应用变更的方式和载体,不变的是在应用持续交付中对于应用变更的持续管理和有监控的多环境推送。
对于 Docker 化的应用,我们大致可以将其持续交付过程划分为两个阶段:构建和装配运行。在搭建 Docker 应用的 DevOps 交付管道时,我们分别用构建工具和 UCD 来完成这两个阶段的工作,如图 2 所示。
图 2.Docker 应用的 DevOps 交付管道
Docker 镜像的构建主要在构建工具中,由开发人员来完成,我们可以用 UCB 或者 Jenkins 来编写自动化的 Docker 镜像构建流程,在开发提交代码后,这个构建流程会被自动触发,最终会在私有仓库目录中添加一个新的镜像版本。
有了构建好的 Docker 镜像版本,测试和运维人员就可以进行应用的装配和运行了。Docker 镜像不同版本的获取,启动相关联的 Docker 容器来运行应用,针对应用的多环境测试以及向公共镜像仓库目录的镜像版本推送等这些活动,都是通过 UCD 来管理的。UCD 不仅可以管理多环境上的复杂应用部署,还能对关键环境(比如生产环境)设置环境门,从而进行质量管控。此外还能引入人工审批来加强对于关键操作和关键环境的监管。
不论用 Jenkins 或者 UCB,两个组件镜像的基础构建流程都是由三步构成。第一步是从 github 中获取 Dockerfile,第二步用脚本或者命令生成 jke.zip 和 init.sql,并拷贝到工作目录(github 库中已默认包含一个 zip 文件和 sql 脚本)。第三步运行 docker build 命令生成 image 并上传至私有仓库。
git clone https://github.com/wanyuxiang/jke-docker-sample
sudo docker build -t jke-db . sudo docker tag jke-db:1.1 192.168.27.100:5000/jke-db:1.1 sudo docker push 192.168.27.100:5000/jke-db:1.1 sudo docker build -t jke-web . sudo docker tag jke-web:1.1 192.168.27.100:5000/jke-web:1.1 sudo docker push 192.168.27.100:5000/jke-web:1.1
构建成功后,在 Docker 的私有镜像仓库 192.168.27.100
中将出现新的 jke-db 和 jke-web 的镜像版本。
UrbanCode Deploy 是企业级的应用部署自动化工具。它以应用为中心,为复杂应用的多环境部署提供了部署工件的版本化管理,部署的多环境管理,图形化的流程设计以及部署审批等多角色协作功能。此外,它还提供了上百个开箱即用的插件,与不同类别和不同厂家的第三方工具集成。
特别的,UrbanCode Deploy 提供了专有的 Docker 插件支持将 Docker 镜像映射为 UCD 的应用组件。在接下来的章节里,我们将详细讨论如何使用 UCD 来做 JKE 应用的持续交付。
首先我们需要在 UCD 中为 JKE Banking 创建一个应用“Dockerized JKE”。根据之前的架构图,JKE 的 DevOps 发布管道将涉及四个环境:开发环境,功能测试环境,集成测试环境以及内部生产环境。在本例中,我们将开发环境放在了构建阶段,因此 UCD 所涉及的装配运行阶段将包括三个部署环境。于是在 UCD 中,我们依次有四个环境,功能测试环境,集成测试环境,内部生产环境,以及用于镜像发布的公共镜像目录环境。
实际中,我们也可以将开发环境放入 UCD,用相同的流程去做部署,测试和镜像推送。唯一需要注意的是开发环境的 Docker 镜像来源,可以是另一个私有镜像仓库,也可以直接从开发环境中获取。无论那种情况,只需要对流程的环境配置做相应修改即可。
如图 3,在应用的首界面我们可以对整个 DevOps 管道的多个环境的当前状态有一个整体的预览,譬如每个环境里应用各组件的当前版本是什么,部署是否合规。
图 3.UCD 中的应用多环境概览
对于不同的环境我们设置不同的环境门,来定义什么样的 Docker 镜像才能部署到特定的环境中。比如,只有通过了 BVT 测试的镜像才能部署到功能测试环境中,而只有通过了三种测试,BVT,功能测试和集成测试后的镜像版本才能进入内部生产环境。
图 4.UCD 中的环境门设置
我们已知 JKE Banking 应用将依赖于一个外部的 DB Server,并由两个部署组件构成。所以在 UCD 中,我们创建了三个应用组件来映射之前已经准备好的 Docker 镜像:jke-web,jke-db 和 mysql。
创建和配置这三个应用组件的操作非常简单。首先我们需要在 UCD 的官方网站下载并安装Docker 插件。在安装后,UCD 中会自动生成 Docker 的组件模板,并包含已经设计好的部署流程。所以我们只需要在创建组件的时候选择使用 Docker 模板,并填写组件镜像仓库目录和运行的相关参数即可。如不填写 Docker 镜像目录参数,UCD 默认会从 Docker Hub 目录中查找和获取 Docker 镜像信息。
图 5.Docker 组件模板-UCD 的 Docker 插件自动生成
从 Docker 组件模板创建 mysql 组件,“Docker Registry”属性留空,使用默认的 Docker Hub Registry 获取 mysql Docker 镜像。
图 6. 组件 mysql 的基本配置
组件 jke-db 和 jke-web 的“Docker Registry”需要填写私有镜像目录的 URL,使得 UCD 从私有镜像目录中获取应用的 Docker 组件镜像。
图 7. 组件 jke-web 的基本配置
如果勾选了“自动导入版本”选项,UCD 会持续的监控镜像仓库是否有新的镜像版本生成。在组件的版本页面,我们可以查看到仓库中该组件镜像的所有版本。对于每个版本,可以用不同的状态来标记该版本的状态,比如用“FVT Passed”标记已经通过功能测试等。版本的状态可以由 UCD 流程自动添加,譬如,在功能测试成功后,为当前的镜像版本添加状态“FVT Passed”。
图 8.mysql 镜像版本管理
在镜像组件版本从镜像目录中被导入到 UCD 时,会被自动加上默认状态“Exists”。
图 9.jke-web 镜像版本管理
在 UCD 中,部署流程分为两个层次,应用流程和组件流程。组件流程是由插件步骤组成,描述某一组件的部署或者配置的特定操作序列。应用流程由各个组件流程拼装而成,描述组件之间的运行依赖关系。在本例中,我们需要创建两个 JKE 的应用流程:
部署 JKE 应用并且运行简单的自动化测试
标记 Docker 镜像版本并且推送到相应的 Docker 镜像仓库目录
首先,我们来看如何设计 Deploy and Test(部署和测试)应用流程以及相关的组件流程。
Docker 插件中提供的 Docker 组件模板中已经创建好了一个“pull and run”的流程,支持在新的环境中获取指定版本的 Docker 镜像并以确定的命令参数来运行。
在将组件镜像版本部署到测试环境后,我们会运行自动化测试来验证应用。UCD 提供了多种测试相关的插件,可以和各种主流的测试工具相集成来做自动化测试。在本例中,我将使用一个最简单的插件来为 jke-web 组件设计一个“test”流程。该插件用 http 的方式来快速检查 web 应用的可用性。我需要做的操作只是将这个插件拖拽到设计界面上,并填入 web 应用的访问 URL 以及页面应该显示的文字。
图 10. 组件流程-jke-web 组件的测试流程
测试通过之后,我们需要更新组件版本的状态,将该测试通过的状态添加到镜像版本信息中。所以我为 Docker 组件模板创建一个新的流程“Set status to version”,用以标记当前组件版本的状态。
图 11. 组件模板流程-设置版本状态流程
最后,我们将设计一个“Deploy and Test”应用流程,来确定如何依次部署各个组件,以及部署之后的测试和状态更新操作。
图 12. 应用流程-应用部署和测试流程
接着,我们来设计应用的镜像发布流程“Tag and Push”。首先我们为 Docker 组件模板创建一个可复用的流程“tag and push”,我们需要依次将插件步骤拖拽到界面,并填入相应的参数。
图 13. 组件模板流程-标记和推送镜像流程
最后创建应用流程“Tag and Push”来发布应用组件镜像。两个组件的镜像发布流程可以并发地去执行。
图 14. 应用流程-镜像标记和发布流程
特别的,在往公共的 Docker 镜像仓库推送镜像之前,我们需要获取相关的管理审批,审批通过后,推送镜像的流程才能运行,否则将自动终止。
完成环境审批设置,首先我们需要在相应的环境配置中勾选“需要核准”,然后再设计审批流程来指定审批角色来对应用或者环境进行核准。
图 15. 环境的核准配置
在勾选“需要核准”选项后,会看到一个核准流程标签页,用来以拖拽的方式设计审批流程。
图 16. 审批流程-公共镜像目录环境的审批
在开发人员利用构建工具构建好了新的 Docker 镜像版本,并上传至私有的 Docker 镜像仓库后,测试和运维人员就可以在 UCD 中进行快速的部署和测试了。
我们以集成测试环境为例,来进行应用的部署和测试。操作非常简单,只需要在环境上点击运行按钮,并选择“Deploy and Test”流程和各组件版本或者包含各组件版本的快照即可。在图中,快照“SN1”包含三个组件的最新可用版本。
图 17. 启动应用部署和测试流程
部署和测试过程会持续几分钟,在运行过程中或者完成后,我们都可以查看运行结果来查找问题或者确认运行日志。最后三个组件的最新版本都会被打上“SVT Passed”状态标签。
图 18. 应用流程执行结果
在最后,我们需要将最新的最符合需求的镜像推送到公共镜像目录中。在启动流程时,我们选择“Tag and Push”流程和之前的快照“SN1”。
图 19. 在公共镜像目录环境上启动推送流程
确定后,审批者会收到需要审批的邮件通知。在其登入到 UCD 后,会看到“Tag and Push”流程正在等待启动,在其做出批准的响应后,发布的流程才正式开始。
图 20. 应用流程核准进度
在流程运行成功后,我们用命令查看 Docker Hub 中的镜像推送已经成功。
$ sudo docker search wanyux [sudo] password for rational: NAME DESCRIPTION STARS OFFICIAL AUTOMATED wanyux/jke-web 1 wanyux/jke-db 1
回页首
Docker 容器技术的应用开发高效性,灵活可移植以及部署高效性使得越来越多的人开始关注并且使用 Docker。Docker 为云环境中的应用以及中间件的部署提供了一种新的解决思路。私有镜像目录的使用为应用的多版本共享提供了一种更简单的方式,而且镜像标签使 DevOps 管道下游的使用者可以方便的选择最新最符合要求的镜像。
UCD 则为 Docker 应用的多环境管理和持续部署管道提供了一个自动化框架,并且为应用持续发布管理中的多种角色提供了一个统一的协作平台。UCD 可以让用户使用相同的操作和流程,快速的搭建和管理一套环境来支持开发和不同测试,甚至生产环境。它使得部署一个应用的新版本如此的快速和便捷,从而能够支持我们持续不断的进行应用发布。
我们期望将 DevOps 领域最热门的两个技术 Docker 和 UCD 结合,为应用的持续部署提供一种更创新更高效的方法。我们也期待两者的结合,能为混合云的持续部署带来一种更优化的解决思路。