«

»

Dec 08 2016

使用GitLab、Jenkins、Docker建立快速持续化集成交付部署方案(三)

 

上一章节中我们完成了对Docker的使用和部署。

本文中我们将完成 GitLab → Jenkins → Docker 的环境,并完成基于GitLab、Jenkins、Docker的面向Web开发的快速部署方案。

 

我们最终得到的结果,将是部署人员只在部署环境下只敲一句命令,就完成整个部署工作。

最终的目的就是接近一键部署,烧锅炉的大叔都会给服务器部署服务了,开除工程师。

文章索引

  1. GitLab、Jenkins、Docker 初始环境安装
  2. 制作 Docker镜像 及 Docker Compose 的使用
  3. 使用 Webhook 自动触发 Jenkins 进行 Docker镜像制作并保存到私有镜像仓库,以及目的机部署(本文)

 

私有Docker仓库

为什么要使用私有仓库

我们最终要得到的交付成果,应是一个 Docker Image。

在某种程度上,不少公司在开发测试阶段可能会考虑直接在开发服务器上生成本地镜像,或是使用 docker save 方式导出tar镜像包文件,在不同机器上进行部署。这种方式对于公司网络环境比较好的情况下确实可以实行,而且对于线上生产环境,某种意义 上人工验收后部署要比全自动部署更放心。

然而更多的企业,外部网络带宽有限,内部网络优化更是渣的可怜。一个镜像包一般都在百M左右,用网络复制可能需要几十分钟甚至半个小时,部署一次环境,等待网络复制的时间,要比 拿一个优盘抱着笔记本乘上几十层电梯钻进机房忍着低温和轰鸣 蛋疼的多。

(已见过不止 3 家公司内部网络是这种情况。而且一般公司的IT部也都是所谓的网管,出问题后 重启、重装、换机 三步走的风格与一般小农村网吧网管也没什么区别。这种职位多数都是公司内部解决职工亲属就业问题内推产生的。神州泰岳全公司都在用12.12.0.0/16这种公网地址当私网地址用,为服务器申请一个静态DHCP地址都会搞得吵架。神州数码这种大公司的网管也在给新员工配置新电脑的时候,装个盗版操作系统都要看手册,还总出错)

所以我们要在这里,充分利用Docker镜像的分层文件系统:没有更新的部分不会生成新的镜像,不会浪费硬盘空间,拉取新镜像时旧镜像也不会消耗流量和带宽。

建立私有仓库

你可以直接执行:

来启动一个仓库容器,默认端口5000,数据将会保存于/var/docker_registry。

注意这是Version 2,对于其他版本请参考其它文档。

注意这是一个HTTP服务,没有加密传输,对于安全性需求,建议自行解决。

相关文档:https://github.com/docker-library/docs/tree/master/registry

本地镜像打tag

这不是一个移动操作,而是一个复制软链接诶操作,在docker images中会新增一个ID相同但tag不同的镜像,不占用硬盘空间。

推送本地镜像到仓库

会将这个镜像推送到your_registry_domain/private-docker-registry/

拉取仓库镜像到本地,或直接执行

pull 和 run,不解释

 

配置GitLab

访问权限

注意,因为GitLab是我们自建的仓库,拥有完全的使用权,所以对于仓库的可视权限将要比GitHub多出两种选项。

  • Private 私有,只有所有者、组内成员或已分配的用户有查看权限(同GitHub收费版的私有仓库)
  • Internal 内部,拥有GitLab账号的成员可以查看,无账号用户无法访问(适合于服务器放在公网但不想公开代码的情景,GitHub没有这个功能)
  • Public 公共,任何人都可以访问(同GitHub免费版的公共仓库)

建议公司内部的代码仓库都设置为 Internal。

使用GitLat Webhook与Jenkins实现持续交付

GitLab等代码仓库其实也支持CI/CD操作,然而我们将要执行的操作对于GitLab来讲过于复杂了,所以这些操作要交给Jenkins这种专门的持续集成工具。为了能在需要时自动触发Jenkins自动操作,我们要使用GitLab的Webhook进行操作。

Deploy Keys

你可以为Jenkins专门制作Deploy Keys,或者干脆在GitLab上增加一个Jenkins账户,用户Jenkins拉取代码。两种方法都可以。

配置Webhook

根据我们之前的安装部署,Jenkins的端口是8081。假设我们的主机域名(地址)为your-what-server,项目为catscarlet/test1.git,则url为

触发条件建议选择 Merge Request event,或干脆手动触发。

这里就有GitLab安装在宿主机的好处了,端口很标准,不然改个ssh端口还要使用git的话,会变得很麻烦。至于https,相信搞得定Let’s encrypt的人很多,但搞不到公司域名的人更多。

 

配置Jenkins

安装必要插件

安装这些插件:

  • Credentials Plugin
  • Git plugin
  • Gitlab Hook Plugin
  • SSH plugin
  • Locale plugin

修改默认语言

Jenkins默认根据用户系统来显示语言,然而其自身的中文翻译挺糟糕的,所以换成纯英文更好一些。

在安装 Locale plugin 插件之后,点击 Manage Jenkins – Configure System,在Default Language处填写en,保存。

修改并发数

因为接下来我们会把项目代码复制到一个统一的临时目录下进行处理,如果这时候有其他项目也在处理,则这个临时文件夹内可能就会有文件混乱的问题。所以我们要把Jenkins的并发数改为1,参数为 # of executors 。对于需要并发处理的正式环境,您需要手动修改临时目录的位置。

新建Jenkins 项目

登录到Jenkins主页,New Item 新建一个 Freestyle project ,命名为test1。

在 Source Code Management 这里,选择Git,并在Repositories填写你的Git项目地址catscarlet/test1.git,Credentials选择你的证书,Branch Specifier选择对应Branch。在 Additional Behaviours 中增加 Clean before checkout。

Build Triggers选择Poll SCM,激活Webhook功能。内容留空,不定时Build,完全由Webhook触发。

在 Build 这里,Add build stemp 增加两个项目:Execute shell 和 Execute shell script on remote host using ssh。

不能选择直接在本地 Execute shell ,因为Jenkins目前是运行在Docker容器内的,与宿主机完全隔离,除了基本的Linux Shell和JAVA的SDK环境之外,容器内没有任何其他东西了,不能使用Docker命令,没有node和npm,不能编译,几乎什么都做不了。

所以我们在这里要分开做两件事:

  • 准备代码,并复制到宿主机环境
  • 登录到宿主机,在宿主机上进行打包。你也可以选择登录到其他主机上,比如一台专用打包服务器。

代码

更改Jenkins的启动方式,额外绑定一个数据卷目录。

我们已经在Source Code Management选择了Git,所以在执行Execute shell之前,Jenkins会先用Git把代码拉取到本地,不需要自己手动执行git pull。

Execute shell:

Execute shell script on remote host using ssh:

需要先在 Jenkins – configuration – SSH remote hosts 中添加对应的服务器登录方式。

这里建议调用从git仓库上拉下来的脚本,而不是把要执行的命令写在Jenkins这里。

project-build.sh

这里建议对每个镜像都手动打包,而不是使用compose打包。一方面compose无法针对镜像打tag(compose更关注于容器而非镜像,容器是NAME而镜像是TAG),另一方面最终部署所需的 docker-compose.yml 中需要编写的是 带仓库路径的 image 而非 build。

我们的理想情况是,部署人员从GitLab获取 docker-compose.yml 之后,执行 docker-compose up,便完成容器部署操作。(面向傻瓜的程序设计,一键部署吔)

测试

GitLab端

在GitLab的Webhooks页面有一个Test按钮,点一下就会触发Webhooks,如果提示 Hook executed successfully: HTTP 200 那么GitLab这端就工作正常。

Jenkins端

Jenkins接到Webhooks后就会开始打包。

  • 灰色表示正在准备
  • 蓝色表示打包中或打包完成
  • 红色表示打包出错

点击进入后可通过左侧的 Console Output 查看控制台的情况,比如 Shell 执行出错在哪里。

注意Jenkins会在Git检查代码变更情况,如果GitLab那段没有新提交的话,Jenkins会认为代码相同,没有必要,会忽略这次打包。所以如果要进行测试的话,可能需要删除上一次的打包结果。你可以在 Polling Log 中查看相关信息。

部署

部署人员从GitLab获取 docker-compose.yml 并复制到目的机,执行 docker-compose up

这回烧锅炉的大叔都会给服务器部署服务了,终于可以把工程师都开除了。

 

总结

本系列文章简单讲述了基于GitLab、Jenkins、Docker的面向Web开发的快速部署方案。文章中没有涉及Docker 1.12以及swarn等相关概念。

Docker 1.11中,基于compose的DAB方案,是以在同一服务器上部署所有服务镜像的方式实现的,这是一种容易简单理解的实现方式。在集群中,每个节点都运行相同的容器组合。多个节点运行相同的容器群,容器群之间隔离没有交互,而容器间紧密结合。

但这是一种可能浪费资源的模式。负责某些服务的容器可能负载非常大,但上下游容器则比较空闲。这种情况下,更希望多个节点都能分担压力大的服务,而对比较闲的服务则减少数量。

另外同一节点上可能会有多个项目,而项目间可能会有相同的无擦别服务,比如php-fpm。更希望复用这一个容器,而不是启用多个相同容器只占内存不干活。

Docker 1.12中实现了这种需求,将分布式的概念从项目分解到容器应用。但目前仍是试验中,所以没有仔细研究,也不建议使用。阿里云在Docker还在1.11版本期间,自己也开发了一个阿里版Docker,实现了1.12中的这个功能,但是限制太多,脚本不兼容,不建议使用。

7 comments

Skip to comment form

  1. 王小白

    你好 我最近在研究jenkins gitlab 结合自动生成docker镜像的问题,目前有些问题没有解决,方便给下联系方式向您请教下吗,万分感谢!

    1. 石樱灯笼

      没有联系方式

  2. godtoy

    请问,有docker-compose部署的方式么? 因为我的项目只是单机,宿主机就一个docker,jenkins泡在容器里面,无法调用宿主机的docker-compose进行重启。我想利用这些工具,实现自动部署

    1. 石樱灯笼

      我单机都是手工维护,或者另外创建一个git项目维护。

  3. 小艾

    博主你好

    问下你这篇博文代码高亮插件用的wordpress的哪一个? 我找了好多都没找到合适的。

    麻烦分享下

    谢谢。

    1. 石樱灯笼

      Crayon Syntax Highlighter

      1. 小艾

        谢谢博主,我也是用的这个, 但是我的为啥那么丑,,,,,,

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据