在本系列文章中,咱们将探讨在容器时代如何在基于Docker的环境中建立连贯的工做流程和流水线来简化大规模项目的部署。另外,咱们还将详细介绍如何利用Docker和Rancher自动化处理这些工做流。git
在上文《将构建环境容器化》中,咱们开始了构建持续集成流水线的第一步工做——构建系统(Build System)的建立。咱们分析了【Build】这一环节的常见的三大挑战——依赖管理、管理环境依赖、复杂项目的漫长构建时间,以及如何用传统工具与方法解决这些问题。接着,咱们分享了如何利用Docker建立容器化的构建系统以更轻松地解决那些传统挑战,包括如何将构建环境容器化、如何使用Docker打包应用程序、如何使用Docker Compose建立构建环境,最终创造一个可重复的、集中管理的、良好隔离的、并行化的构建系统。github
如今咱们已经将【Build】系统建立好了,那么在本文中,咱们将为示例的应用建立一个持续集成流水线。这样咱们既能够确保遵循最佳实践,又能够确保彼此冲突的那些变化不会相互做用、引起问题。不过,在咱们为代码创建持续集成以前,咱们先花一点时间讨论如何将代码划分到分支中。docker
分支模式shell
在咱们实现持续集成流水线的自动化时,一个须要考虑的重点是团队遵循的开发模式。这个模式一般由团队如何使用版本控制系统来决定。因为咱们的应用程序托管在git仓库中,所以咱们使用git-flow模型进行分支、版本化以及发布咱们的应用程序。它是基于git仓库上最经常使用的模型之一。简而言之,该模型的思想是维护两个分支:一个开发(者)分支,一个主分支。每当咱们想开发新功能时,就会从开发分支建立出新的分支,并在功能开发完成时,将它合并回来。全部功能分支都有开发人员单独管理。一旦将代码提交到开发分支,CI服务器将负责确保分支始终可以编译、经过自动化测试而且能够在服务器上进行QA测试和评审。当咱们准备进行发布时,能够从开发分支建立一个发布,并将其合并到主分支中。被发布的特定的commit hash也会使用版本号进行标记。被标记好的发布项接着就能够被推送到Staging/Beta或者生产环境中。数据库
下面咱们将使用git-flow工具来帮助管理咱们的git分支。安装git-flow请参考这里的说明:https://github.com/nvie/gitflow/wiki/Installation。安装好git-flow,你就能够经过下面所示的git flow init命令配置你的仓库。Git flow会问一些问题,咱们建议你使用默认的设置便可。执行过git-flow命令后,它将建立一个开发分支(若是原先没有开发分支的话),并将其检出做为工做分支。服务器
如今,咱们使用git flow输入git flow feature start [feature-name]命令建立一个新功能。一般作法是用ticket/issue id用做功能的名称。好比,若是你使用的是Jira处理ticket,那么ticket id(例如,MSP-123)就能够做为功能名称。你还会发现当你使用git-flow建立新功能时,它将自动切换到功能分支。curl
到了这一步,你能够去完成该功能所需的所有内容,而后运行自动化测试套件以确保一切正常运转。一旦你准备好发布工做,只需告诉git-flow去完成这一功能便可。根据你对该功能的实际须要,你想要进行多少次提交均可以。在个人这个示例中,从咱们的目的来看,咱们只需更新README文件,并经过输入“git flow feature finish MSP-123”来完成更新。工具
须要注意的是,git flow合并了开发分支的功能,删除了功能分支而且返回到了开发分支。此时,你能够将开发分支推送到远程仓库(git push origin develop:develop)。 当你提交了开发分支,CI服务器就会接管持续集成流水线。对于更大的团队来讲,一种更合适的模式是在完成功能以前将功能分支推送到远程,让它们经评审(review)后,使用pull request来合并到开发分支中。post
使用Jenkins建立CI流水线单元测试
在这一节,咱们假设你已启动并运行了一个Jenkins集群。若是没有的话,你能够在这里使用官方的Jenkins镜像:https://hub.docker.com/_/jenkins/ ,在这里能够看到更多关于创建可扩展Jenkins集群的内容:https://rancher.com/deploying-a-scalable-jenkins-cluster-with-docker-and-rancher/ 。在你有了运行的Jenkins集群后,咱们须要在Jenkins服务器上安装下面的插件和依赖项:
Jenkins Plugins 2.32.2+
Git Parameter Plugin 0.8.0+
Parameterized Trigger Plugin 2.33+
Copy Artifact Plugin 1.38.1+
Build Pipeline Plugin 1.5.6+
Mask Passwords Plugin 2.9+
Docker 1.13.1+
Docker Compose 1.11.1+
安装好须要的插件后,咱们就能够在【Build流水线】中建立最初的三个任务:编译、打包和集成测试。这些将做为咱们持续集成和部署系统的起点。
构建应用
序列中的第一个任务将会在每次提交后从源码控制中检出最新的代码而且确保其可编译。它还会运行单元测试。若是要在咱们的示例项目中设置第一个任务,选择New Item->Freestyle Project。进入项目配置视图中,选择General选项卡以及“The project is parameterized”选项。添加一个叫作GO_AUTH_VERSION的git参数,将参数类型设置为Branch(分支)或者Tag(标记)。接下来选择Advanced配置参数,使用Tag Filter设置获取匹配“v”的全部标记(好比v2.0)。将Default Value设置成develop(开发分支)。这将有助于从Git获取版本标签列表,并为该任务填充选项菜单。若是该任务要在没有给定值的状况下自动触发,那么GO_AUTH_VERSION默认设成develop(开发)分支。
接下来,在Source Code Management选项卡部分添加仓库url,指定分支为${GO_AUTH_VERSION},这样手动构建时将会使用git参数来选择分支或标记进行构建及设置轮询间隔。这样一来,Jenkins就会持续追踪咱们开发分支的将来全部更改,在咱们的CI(和CD)流水线中自动触发第一个任务。这里要注意的是,GO_AUTH_VERSION的默认值(好比开发分支)将用于自动检测到的更改。
如今在Build选项卡部分选择Add Build Step > Execute Shell并从本章前面部分复制docker run命令粘贴到这。这样能够从Github得到最新的代码,并将代码构建到go-auth可执行文件中。这里须要安装并运行docker。若是你使用的是Linux服务器,可能还须要在docker客户机命令中添加sudo以便可以访问docker守护进程。
在构建步骤以后,咱们须要添加两个后续步骤,其中Archive the Artifacts(工件归档)将go-auth二进制文件和帮助脚本归档到项目中。咱们在任务中须要指定下列的工件进行归档。
接着咱们使用Trigger parameterized builds(触发器参数化构建)启动流水线中的下一个任务,以下图所示。在添加Trigger parameterized build时,请确保是从Add Parameters中添加的Current build parameters。这样可让当前任务的所有参数(好比GO_AUTH_VERSION)用于下一个任务。请留意在Trigger parameterized build部分中用于下游任务的参数名称,咱们将在下面的步骤中用到。
构建任务的日志输出应该像下面展现的这样。你能够看到咱们使用了docker化的容器来执行构建。构建时将使用go fmt来修复代码中任何格式的不一致,而且执行咱们的单元测试。若是出现测试失败或者编译不经过,Jenkins就会检测到失败。此外,你应该经过email或者chat integrations(例如Hipchat或者Slack)设置通知,这样在构建失败时就能通知到你的团队,快速地修复它。
打包应用
代码编译经过了,接下来咱们就能将它打包进Docker容器中。建立打包任务的方式是,选择New Item > Freestyle Project并给你的第二个任务起一个名称,该名称对应于在先前任务中指定的内容。和以前同样,该任务也是一个带有GO_AUTH_VERSION参数的参数化构建。要注意的是,这里和全部后续的任务中,GO_AUTH_VERSION只是一个默认值为develop(开发分支)的string参数。咱们但愿它的值是从上游传过来的。
和以前同样,添加构建步骤来执行shell。注意这里你不须要指定SCM设置,由于咱们将从前一个构建生成的工件中提取所需的二进制文件和脚本。注意一下,咱们这里是先建立未标记的usman/go-auth,以后再从新标记,这样咱们就能够在后面执行集成测试,搭建好未打标记的容器环境。
为了构建Docker容器,咱们还须要前一步中构建的可执行文件。为此,咱们增长一个构建步骤复制上游构建中的工件。这样能够保证咱们有可用于Docker构建命令的可执行文件,该命令能够打包到Docker容器中。注意这里咱们选择了flatten目录来保证全部工件都复制到当前项目的根目录中。
咱们一直在使用GO_AUTH_VERSION变量标记咱们正在构建的镜像。在默认状况下,开发分支的变动,总会构建usman/go-auth:develop并覆盖现有的镜像。在下一章中,咱们会发布应用程序的新版本并从新审视这个流水线。
和以前相同,使用了Trigger parameterized builds下(包含了Current build parameters)的后构建(post-build)来触发流水线中的下一个任务,该任务将使用咱们刚刚构建好的Docker容器以及在以前章节中详述的Docker Compose来执行集成测试。
执行集成测试
接下来是执行集成测试,先要建立一个新任务。和打包任务相同,新任务是一个使用GO_AUTH_VERSION string变量的参数化构建。而后从构建任务中复制工件。这一次咱们将使用上面的Docker Compose模板来搭建一个多容器测试环境,并对咱们的代码执行集成测试。集成测试(不一样于单元测试)一般是与正在测试的代码彻底隔离的。所以,咱们会用到一个shell脚本,它能够针对咱们的测试环境执行http查询。在执行shell命令中,将目录修改成go-auth并执行integrationtest.sh。
脚本的内容能够在这里找到:https://github.com/usmanismail/go-messenger/blob/master/go-auth/integration-test.sh。咱们用Docker Compose搭建咱们的环境,而后使用curl发送http请求到搭建的容器中。这项任务的日志将会和下图显示的类似。Compose将会启动一个数据库容器,并将它链接到goauth容器。数据库链接以后你应该会看到一些列“Pass: …”信息,说明各项测试都在运行和验证。测试完成后,compose模板将会自行清理数据库和go-auth容器。
通过了三个任务的设置,你就能够在Jenkins视图中选择【+选项卡】,选择build pipeline view来建立一个新的构建流水线视图。在弹出的配置界面中,选择你编译/构建的任务做为初始任务,而后选择ok。如今你应该能看到CI流水线已经成型。这将给你一个可视化引导,展现每一个提交是如何经过你的构建和部署流水线的。
当你更改开发分支时,你会注意到流水线是由Jenkins自动触发的。若是要手动触发流水线,选择你第一个(构建)任务,运行它。系统会要求你选择git参数的值(好比GO_AUTH_VERSION)。不指定的话会执行默认值,而且会运行针对开发分支中最新内容的CI流水线。固然,你能够直接在流水线视图中单击“Run”。
咱们快速回顾一下到如今为止咱们所作的工做。咱们经过如下步骤为咱们的应用程序建立了CI流水线:
使用git-flow添加新功能,并将他们合并到开发分支中。
跟踪开发分支的变化,在一个容器化环境中构建咱们的应用程序
将咱们的应用程序打包到docker容器中
使用Docker Compose搭建短生命周期环境
执行集成测试以及清理环境
经过上面的CI流水线,每当新功能(或者修复)合并到开发分支时,CI流水线就会执行上述全部的步骤,建立出“usman/go-auth:develop” Docker镜像。此外,咱们在接下来的章节中将构建更深层的集成部署流水线。另外由于该视图有清晰的测试阶段,你还可使用此视图将应用程序版本推广到各类部署环境中。
总 结
在本章中,咱们分享了如何利用Docker为咱们的项目建立一个持续集成流水线,该流水线是集中管理的、可测试的,而且在机器和时间上可重复。咱们可以根据须要对各类组件的环境依赖进行隔离。这是咱们将来部署一条更长的基于Docker构建和部署的流水线的起点,咱们将在下一次的文章中继续构建这一流水线的余下部分并将过程经验记录下来。
咱们流水线的下一步是建立持续部署,后续文章咱们将展现如何使用Rancher部署整个服务器环境来运行代码,咱们还将介绍如何为大型项目设置长期运行的测试环境和持续部署流水线的最佳实践。