Python 还能承担下一个时代的发展重任吗?Mojo 语言的横空出世对 AI 研发生态有什么影响? 了解详情
写点什么

Docker 持续部署图文详解 | 高效运维最佳实践 06

  • 2015-07-30
  • 本文字数:3210 字

    阅读完需:约 11 分钟

专栏介绍

“高效运维最佳实践”是 InfoQ 在 2015 年推出的精品专栏,由触控科技运维总监萧田国撰写,InfoQ 总编辑崔康策划。

前言

关于 Docker 的文章铺天盖地,但精品文章往往翻译居多。都说 Docker 天生适合持续集成 / 持续部署,但同样,可落地、实际可操作性的文章也很罕见。

基于这些情况,虽然我们专栏定位为运维管理性文字,但本篇是个特例,实操性的案例讲解——JAVA 项目如何通过 Docker 实现持续部署(只需简单四步),即:

开发同学通过 git push 上传代码,经 Git 和 Jenkins 配合,自动完成程序部署、发布,全程无需运维人员参与。

这是一种真正的容器级的实现,这个带来的好处,不仅仅是效率的提升,更是一种变革:

开发人员第一次真正为自己的代码负责——终于可以跳过运维和测试部门,自主维护运行环境(首先是测试 / 开发环境)。

难者不会,会者不难。通过简单的 4 个配置,即可优雅地实现持续部署。本文依惯例放上目录,请享用。

  1. 持续部署的技术思路
  2. 效果展示
  3. 配置 Git 和 Jenkins 联动
  4. 配置 Jenkins 自动更新代码
  5. 效果图文详解
  6. FAQ

好吧,我们正式开始。

1. 持续部署的技术思路

在本例中,假设我们 JAVA 项目的名称为 hello。简要的技术思路如下。

本案例中假设代码托管在 git.oschina.com 上,Jenkins 和 Docker Registry(类似于 yum 源)各运行在一个 Docker 容器中。JAVA 项目自己也单独运行在一个叫 hello 的容器中。

本文采取的持续部署方案,是从私有的 Docker Registry 拉取代码。有些变通的方案,把代码放在宿主机上,让容器通过卷组映射来读取。这种方法不建议的原因是,将代码拆分出容器,这违背了 Docker 的集装箱原则:

这也导致装卸复杂度增加。从货运工人角度考虑,整体才是最经济的。这样,也才能实现真正意义的容器级迁移。

或者说,容器时代,抛弃过去文件分发的思想,才是正途。本文最后的问答环节对此有更多阐述。

容器即进程。我们采用上述方案做 Docker 持续部署的原因和意义,也在于此。容器的生命周期,应该远远短于虚拟机,容器出现问题,应该是立即杀掉,而不是试图恢复。

2. 效果展示

本文最后实现的效果,究竟有多惊艳呢?且看如下的演示。

2.1 程序代码更新前的效果

我们以时间戳来简洁、显式的表述程序更新情况。

2.2 提交程序代码更新

本例中,我们把首页的时间戳从 201506181750,修改为 201506191410(见如下)。

2.3 上传新代码到 Git

顺序执行如下操作,输入正确的 git 账号密码。

然后呢?

然后什么都不用做了。端杯茶(如果不喜欢咖啡的话),静静地等待自动部署的发生, 旁观一系列被自动触发的过程,机器人似的运转起来(请容稍候再加以描述)。

为什么需要 3~5 分钟?只是因为本案例中的 JAVA 项目,需要从国外 download Maven 程序包,以供 Jenkins 调用和编译 JAVA。正式应用环境中,可以把 Maven 源放在国内或机房。如果仅仅需要对 PHP 项目做持续部署,那就更快捷了。

2.4 查看代码更新后的效果

在静静地等待几分钟后,新的代码确实已经自动部署完毕。

那么,这一切怎么实现的呢?很复杂么?不然。只要按照如下几步,便可快速实现哦。

3. 配置 Git 和 Jenkins 联动

这个过程也是难者不会,会者不难。主要分为如下三步。

3.1 Jenkins 配置 Git 源

Jenkins 中新建项目 java-app,并配置从 Git 拉取程序代码。具体如下:

3.2 Jenkins 配置远程构建

Jenkins 中配置 token,以供 git 远程调用时使用。

3.3 Git 开启钩子

怎么让 Git 在接收到用户更新的代码后,把消息和任务传递给 Jenkins 呢?这借助于 Git 的 hook 功能,配置起来也非常简单,如下。

4. 配置 Jenkins 自动更新代码

Jenkins 的主要工作是配置“远程构建”。在接收到 Git 传递过来的消息后,触发这个远程构建(到目标服务器),按照预定义的任务列表,执行一系列的工作,重建容器等。详见如下:

我们把其中最关键的 Shell 脚本内容摘抄出来。这些 Docker 相关操作,在第 1 部分“技术思路”已经提及,不再赘述。

5. 效果图文详解

在 2.3 这个章节中,我们当时的操作如下,这个目的是向 Git 提交更新代码。

当时并没有细说后续发生的事情,既然上面已经说清楚了原理,那我们就可以接下来说说实际发生的事情啦。

5.1 上传代码到 Git

这里貌似整个过程已经完成并顺利退出。其实,后台的工作才刚刚开始哦。

这时会触发 Git 服务器向相应的 Jenkins 服务器发出一个操作请求,此工作太过迅速,也没啥好说的,我们接下来看 Jenkins 都干啥子了。

5.2 Jenkins 进行的精彩互动

如下这个自动运转的过程,让我们有些许成就感,值得端杯咖啡(如果不喜欢茶的话),静静观赏。

1)Jenkins 会自动"冒出来"一个构建任务。

2)我们点进来,看看具体操作日志。是的,正在接受来自 Git 的任务。

3)下载 Maven 相关的软件包(就是这个过程慢)。

4)下载完成后,就开始利用 maven BUILD 新的 hello 项目包。

5)然后重建 Maven 容器,构建新的 Image 并 Push 到 Docker 私有库中。

6)最后,重新把 Docker 容器拉起来。这样,又新生了。呵呵

6. FAQ

问题 1:采用这么相对复杂的办法(而不是把更新代码放在宿主机然后卷组映射),是因为项目基于 JAVA 么;是否 PHP 项目就可以采用更新代码放在宿主机然后卷组映射这种方式?

回答 1:将代码拆分出容器,违背了集装箱原则。导致装卸复杂度增加。从货运工人角度考虑,整体才是最经济的。一切版本化。抛弃过去的文件分发。这是正途。至于文件大小,大的 war 包也就 50M 或 100M,在现有网络下不成问题,性能问题最好优化。另外建议关注 docker 2 docker,p2p 传输。

问题 2:如果整体代码超过 500m 或者 1g 以上,整体集装箱是否就不太好了?如果容器与代码分离,镜像就 100m 左右(2 层,base+ 服务),然后代码的话,是放到共享存储里,每个代码有更新,比如 svn 的代码,可以直接在共享存储里进行 svn update 就可以控制版本

回答 2:如果你的代码 500M,那只能说明业务开发该打板子了。

问题 3:如果测试环境使用您提供的完整集装箱服务还行,但在生产环境,集群里运行 docker 做应用,如果每个容器都是有完整的代码,是否有点臃肿,不如每个集群节点里就运行基础服务镜像,通过卷组功能绑定共享存储里的代码,加上 Crontab、Python 和 Shell 脚本,这样每次代码更新就 1 次就行了。

回答 3:环境一致性,在过去从来没有解决好。10 年前我们做 paas 时,和这个做法类似。不是说不好,时代变了,用脚本东拼西凑,终究难有好的系统。不能只考虑现在的方便,容器技术和 vm 如果类比,我觉得会让自己下决定时很纠结。

补充 3:脚本一般是典型的运维工程师思维,quick & dirty。一般很难做成一个产品或者系统。整体考虑和扩展性考虑都比较少。现在做 docker 的难点在于到底怎么看待它。到底是拿它做调度的基本单位,还是部署的基本单位考虑清楚?再聊方案。

关于作者

萧田国 ,男,硕士毕业于北京科技大学,触控科技运维负责人。拥有十多年运维及团队管理经验。先后就职于联想集团(Oracle 数据库主管)、搜狐畅游(数据库主管)、智明星通及世纪互联等。从 1999 年开始,折腾各种数据库如 Oracle/MySQL/MS SQL Server/NoSQL 等,兼任数据库培训讲师若干年。

曾经的云计算行业从业者,现在喜欢琢磨云计算及评测、云端数据库,及新技术在运维中的应用。主张管理学科和运维体系的融合、人性化运维管理,打造高效、专业运维团队。

个人微信号:xiaotianguo。如需更多了解,请百度“萧田国”。

张春源,目前任职 cSphere。国内最早期的 Docker 实践者,在生产环境拥有一年多的 Docker 容器管理经历。深刻理解 Docker 对于开发、测试以及运维的价值。擅长利用 Docker 构建整个 DevOps 自动化平台。热爱专研 Dockerfile 这门艺术,并对 CoreOS 有深入研究。


感谢崔康对本文的策划,丁晓昀对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群)。

2015-07-30 00:1011530

评论

发布
暂无评论
发现更多内容

加密算法是什么?有哪几种类型?有什么用?

行云管家

加密算法

云服务器的四大作用讲解-行云管家

行云管家

云计算 服务器 云服务 云服务器

kubernetes下jenkins实战maven项目编译构建

程序员欣宸

DevOps jenkins 11月月更

软件测试校招面试题 | 实习生和应届生有什么区别?

测试人

面试 软件测试 自动化测试 测试开发 实习

洞见科技姚明:隐私计算行业将会发展为多层级多领域的数据智能流通网络

洞见科技

node.js的path路径模块和http模块

急需上岸的小谢

11月月更

张文歆:思维需碰撞,才有更大的“火花”|对话 Doris

SelectDB

开源 职场 成长 学习路线 开源治理

打开时空隧道,重演云栖72小时云世界

阿里云视频云

阿里云 云栖大会

node.js的模块化与npm

急需上岸的小谢

11月月更

StarRocks 与 DataPipeline 完成兼容性互认证,携手共建数据基础设施生态

StarRocks

数据库

视频清晰度优化指南

得物技术

深度学习 算法 H.265 视频质量 图像超分

DTSE Tech Talk | 第11期:深入浅出畅谈华为云低时延直播技术

华为云开发者联盟

云计算 后端 华为云

分布式锁

急需上岸的小谢

11月月更

EventBridge 生态实践:融合 SLS 构建一体化日志服务

阿里巴巴云原生

阿里云 云原生 EventBridge

「Go实战」在 Go 项目中基于本地内存缓存的实现及应用

Go学堂

golang 缓存 开源 程序员 性能

千万级学生管理系统设计试卷存储方案

Geek_92ba6f

有奖报名|StarRocks 获开源热力值增速第一,有你的贡献

StarRocks

数据库

学历不是问题!社招大专老哥阿里 腾讯Java面试,上岸入职京东

钟奕礼

java程序员 java面试 java编程 #java

IM通讯协议专题学习(二):快速理解Protobuf的背景、原理、使用、优缺点

JackJiang

HMS Core手语服务荣获2022中国互联网大会“特别推荐案例”:助力建设数字社会

HMS Core

手语 HMS Core

探知数字化研发4 - 底座篇

薛飞

数字化研发 数字化底座

HUAWEI DevEco Studio 3.1版本发布,配套ArkTS声明式开发全面升级

HarmonyOS开发者

HarmonyOS

精彩议程更新,从云原生到 Serverless 的思考和收获,邀你共同见证丨PingCAP DevCon 2022

PingCAP

TiDB

首次!阿里巴巴团队共同携手编写“大厂面试参考指南”v1.0版本

钟奕礼

Java 面试 java程序员 java 编程 #java Java 面试题

计算机网络:IEEE 802.11无线局域网

timerring

计算机网络 11月月更

解析 RocketMQ 多样消费功能-消息过滤

阿里巴巴云原生

阿里云 RocketMQ 云原生

一文带你回顾操作系统的内存知识点

华为云开发者联盟

操作系统 开发 内存 华为云

战略合作再升级!合合信息与腾讯云联合推出海外智能风控方案

科技热闻

软件测试 | 接口自动化你不懂?听HttpRunner的作者怎么说

测试人

软件测试 自动化测试 接口测试 接口自动化 HttpRunner

应用程序现代化指南

世开 Coding

应用现代化 软件升级

阿里P8出,入职阿里必会199道SpringCloud面试题,你能掌握多少?

钟奕礼

Java java程序员 java面试 java编程

  • 扫码加入 InfoQ 开发者交流群
Docker持续部署图文详解 | 高效运维最佳实践06_DevOps & 平台工程_萧田国_InfoQ精选文章