应用Docker进行持续交付:用技术改变交付路程

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
传统型负载均衡 CLB,每月750个小时 15LCU
简介: 在第13期云栖TechDay活动上,唐容为大家分享了《应用Docker进行持续交付》话题。他先谈了传统CD(持续交付)过程中遇到的问题,然后解释Docker的原理及它为什么能够改变持续交付,最后分享了应用Docker化交付的过程和适用场景。

在第13期云栖TechDay活动上,唐容为大家分享了《应用Docker进行持续交付》话题。他先谈了传统CD(持续交付)过程中遇到的问题,然后解释Docker的原理及它为什么能够改变持续交付,最后分享了应用Docker化交付的过程和适用场景。


下面是演讲内容整理。



背景


互联网行业都是比较新兴的产业。市场需求量不断变化,产品不断变化,导致我的开发须不断变化,最后导致我必须持续不断的去交付、更新我的生产环境。


时间长了就会产生一系列的问题。其中最主要的问题是,老的运维人员把生产环境做好,一旦他离开,就会导致继任者不知道该对这个环境应该做怎么样的操作,因为他不知道前面的人做了什么。


还有一种情况,通常生产发布往往是在生产环境调试非常多次,最后才能发布下去。运维最辛苦,但是需求又不断的变化,产品又在不断的变化,我们还是必须不断更新。


传统CD过程中遇到的问题


传统解决方法是CI(持续集成)或CD (持续交付)。即把开发生产交付的过程变成一个环,一个可以不断循环的过程。




  • 集成:就是两个东西在一起:提交文档时代码和代码在一起,编译时代码和逻辑在一起,测试时代码和功能在一起,生成到部署和生成发布时就是代码和系统,系统和系统之间在一起。每次两个东西在一起就是集成。

  • 持续:它就跟体检一样,它只是能帮你很快速的在前面发现你的系统中出现的问题,让你在前面就把这个问题解决了,不至于到最后发布的时候发现:有功能没测过就被合起来了,漏了一个功能,哪块代码有点问题。总之就是说要持续做这个事情。


  • 有效反馈:在持续集成管道的流程图里,每一个结点就是一次有效的反馈。



举个最简单的例子,开发人员提交完代码之后,你要做到的第一点是和别的代码没有冲突,并且能编译通过,然后单元测试能通过,这个时候确实没有这个工程师的事情了,可以去做别的事情了,这个就叫有效的反馈。


我只是告诉你说我的代码没有冲突了,我去干别的事情,突然别人告诉我,你代码提交上来,感觉整个系统编译最后失败了,还是得去修复。所以说有效的反馈和持续进行,是整个里面最重要的两件事情。


我每做一个结点得到一个有效的反馈,这个有效的反馈需要非常及时的去恢复到这个development的地方。然后恢复到开发人员这里的时候,他就知道后面该做什么样的事情。


还有一种情况,一般来说开发人员只要保证自己的单元测试通过了,去干别的事情;测试人员来负责系统的功能,或者集成的测试。可能开发提交了10次代码才进行一次功能测试。两个人节奏不同,所需要得到反馈节奏也不同的,所以两个结点是分开的。



构建CD过程所需的环境




一般来说在一个公司里面,或者一个项目,需要搭建一个不同的环境。这个环境首先有托管,单位测试,有一套打包build的环境,最后还会有一个部署的服务。


企业生产环境是在公有云上,是一个公有云环境。我们开发过程是在线下环境,这就造成了最后发布的时候,一是我发布的时候需要一个环境,二是公有云跟线下开发环境不一致,可能导致很多问题。


CD过程中遇到的问题:


即便按照流程去做持续交付,系统地搭建出来整个持续集成的系统环境,一样会遇到七七八八这样的问题。就算是同一种语言,每一个开发者所依赖语言环境、依赖的包不一样,就会导致有非常多的编译环境,维护起来就很困难。



问题的根源:


开发者交付的只有代码和代码的依赖,而运维需要的除了代码,还需要环境,环境描述,依赖,数据库,缓存,而不仅仅是代码。




变革软件交付方式的技术:Docker




如果交付的代码中有一个描述文件,不仅能描述代码本身的依赖,还描述整个环境的依赖以及环境的描述,catch,config,变量,容器,生成环境需要的jar包等。


这就像把一堆零散的代码和我要的所有东西装在集装箱里,真正去交付给运维时,相当于把这个集装箱运行起来。集装箱最核心的特点,是有一个集装箱的方式去运行,它包含所有的环境依赖,所以在任何地方运行集装箱所达到的结果都是一样的。因为达到了环境一致性。


没有Docker之前我们有很多规范用来约束。Docker是通过技术手段约定,甚至通过技术能力从底层改造。


Docker的能力


  • 描述环境的能力(Docker file文件,这个文件能描述软件所需要的整个环境)
  • 分层文件系统 (分层文件镜像Docker image,解决包管理问题,我们每做一个操作,都能够描述出来作为一层,这一层就是每一层版本管理。)
  • 运行时屏蔽操作系统差异


Docker是一种容器技术


容器技术与传统虚拟机技术的最大差别在于 : 所有容器是进程级的,它用到的操作系统的内核是父母机的操作系统内核,它没有完整的os层。


(虚拟化技术在物理机层面上有一层软硬件结合的虚拟化技术,虚拟化技术上面每一个虚拟机是一个完整的操作系统,有很好的隔离性,但可能启动需要几分钟。)


容器技术最大的好处在于它是进程级的,是一个秒级启动,没有传统的一虚几的概念。理论上宿主机上能启动无数个Docker进程。


Docker进行软件交付的三步:


  • Build :描述依赖操作系统,环境描述,启动端口,执行脚本。描述文件存储为Docker镜像(Docker image),放在本地存储仓库里
  • Ship:把镜像传递(Push)给远端的Docker Registry里。
  • Run:运行时从公共Registry获取(Pull)镜像。这个集装箱,是一个环境描述的本身,是一个完整体,在任何环境运行的结果应该是一样的。


官方案例:BBC news




BBC News是一个全球新闻网站的一个公司。他们当时遇到问题是,他们全球有500多个开发,分布在全球的各地。然后有十多种CI的环境,因为全球各地的人用的语言也不一样。从代码到交付这个过程,它都需要没办法运行,需要等待,然后十多种CI环境无法统一的管理,这是最大的问题。


如何使用Docker


第一步:安装Docker运行环境。




Docker运行环境只有一个限制,即Linux操作内核必须高于2.6.3的某个版本。Docker公司推出Docker machine技术,有一个toolkit,这个工具集可以区分你的操作系统,提供不一样的安装包,一键安装。这个工具屏蔽了底下OS的差异。同时有不同的云驱动,就是说像阿里云上面有ECS driver、AWS、GCE等等,每一个运营厂商一般都提供将Docker安装在他们上面的驱动。


第二步:用Dockerfile 描述你的应用环境



  • 方案一

第一种是运维把原来搭建一个环境要的所有东西都列出来,变成Dockerfile这种描述语言。这个语言它其实不是某一种开发语言,只是定义出来的一个描述语言。这个描述语言其实很简单,它必须有一个FROM, FROM上一个环境。有了这个概念,也可以很好的传承这件事情,去分割工作职责。run执行命令, event环境变量,然后还有add expose cmd 等等的命令。


  • 方案二

如果有人已经写好标准的Java环境,就能直接把环境拿过来,把jar放进去就能用。


如果服务被拆成微服务的架构 ( 每一个服务不是一个war包而是一个jar ) ,那么所有的微服务共用一个Docker 镜像。(不同语言提供API功能,许多并不需要依赖,只需要语言的运行环境就可以了。)


现在官方提供各种环境的Docker 镜像,FROM官方的镜像,把jar放进去就可以。有一些开源软件,把镜像下下来就能直接运行了,如Gitlab。有了Docker技术,搭一些开源的工具系统也会变得非常容易。


第三步:用Docker搭建编译/单元测试环境




  • 应用本身的编译和Docker环境的编译分开


如果放在一起的话,势必要把代码拷到Docker环境里面去。在Docker build的过程中,先build了我的代码,然后再把我的代码删掉,因为Docker(统一下全文大小写) 有分层的原理哪怕我在我Docker file里面写,我先拷贝我的一些.java连接过来之后, build一个jar,再把.java删掉。只要获取到你拷贝.java这一层,就可以获取到你源代码。而这个Docker容器真正运行在生产环境时,我们是不希望代码在生产环境里面出现的。


  • 编译和测试的环境分开


本着这个叫做Docker镜像最小化的原则(就是我要什么我装什么,我不要什么我就不装)一个Java(统一下大小写) + NodeJS运行环境,我生产环境运行起来了之后,我不需要用到ping。ping是运维调试的时候需要的。你编译的时候可能需要很多编译环境的依赖,编译环境的依赖在生产环境运行是不需要的,所以基于这一点,我们也建议把环境分开。建议你们编译环境也通过Docker实现。


编译环境是一个build环境,测试的环境是一个run的环境。我对程序build的一个环境,简单来说下过程:


代码可以通过-v的方式就是加载到容器里,有一个叫build的container,针对不同的语言进行build,变成binary依赖包这样的文件;然后再把这些文件add拷贝到Docker file里面去,再进行Docker build。两步build变成最终可以运行的Docker image。


通过第一步build的时候,Docker file里面拷贝过来的是binary,是真正要运行的东西,而不是源代码。


然后image build出来之后,可以去启动不同的脚本(让真正的运行跑生产,我可能有一个跑生产的脚本;我可以运行一个跑测试,然后去执行测试脚本)。用Docker去跑集成测试其实也不是很难。因为应用本身已经Docker化了,只要Docker跑起来,去执行一个测试的命令,不管是执行数据库还是执行什么,它都是执行测试的过程。人工测试之外的,只要是能够脚本化测试的东西,都可以拿Docker去编写。


第四步:用Docker描述依赖环境


应用程序并不是有image就可以了,即使不依赖其他人的应用程序,都一定会依赖数据库。测试的时候要造一个数据就得有数据库在。


Docker公司还提供了一个Docker compose。Compose即编排,编排的意思是可以管理多个Docker image。




这个图就是Docker compose的官方介绍图,简单来说分三步:


第一步:写Dockerfile描述应用环境。


里面写工程目录是什么,拷贝了一个requirement一个文件到目录code下,pip install 一个ruby程序,运行这个程序。


第二步:通过.yml去描述依赖关系


绝大多数的情况下,单容器是无法直接解决问题的。跑测试的时候我需要依赖一个DB,只要有一个DB能够提供存储的功能,当我要的时候它能够提供给我就可以了。这个东西就是来描述一个或多个web程序,DB等等非常多的东西的。


当我这个程序需要依赖一个DB的时候就写一个link,起一个名字叫link DB。通过Docker compose这个命令,去把一组Docker image一起运行起来,它里面依赖关系是通过compose .yml去描述的。


第三步:用Docker把整体的集成或者运行环境都描述出来


Docker运行起来了之后,除了Docker本身,APP本身前面需要负载均衡后面需要数据库,然后可能还需要文件存储,还需要缓存,然后需要其他的一些东西。


  • 数据库

Docker其实根本不关心数据库搭在哪,也不关心怎么搭的。开发控制过程中,去依赖启动一个DB,所有的DB官方已经提供了image,只要把这个DB container从官方拉下来。一个MySQL DB5.7的应用,在真正使用之前启动这个MySQL DB的container,看一下配置,可能改一些语言描述。比如说我可以在compose里面去运行,第一行写依赖,运行MySQL 5.7;第二行写环境变量,把我的配置文件替换成它的配置文件,设置一下启动密码,然后启动的端口是3306还是多少。


并且在web程序里面,测试的时候不用去写测试依赖的MySQL id是什么,写MySQL就直接能通过,因为它就是compose里面描述的这个MySQL。通过之后我只要告诉它密码是什么就能连上数据库。而Radis起个名字提供端口就可以了,它只要缓存服务。


  • 负载均衡

负载均衡也挺简单,不管是Ngix , Haproxy也有官方的东西。最后开发人员真正关心的,就是怎么把自己的应用程序拿Docker描述出来。描述出来之后,写好compose,前面Nginx用的什么版本,什么样配置,后面的这个APP启动。


  • 存储

一是我通过-v挂在宿主机,二是把数据库的存储,和我初始化的数据,挂在我本地的一个目录下面,这个时候每次运行就不用再初始化,只要去点APP就可以了。


而真正运行生产环境的时候,数据肯定是在一个云存储或者说存储在云设备上。这个时候就可以选择一些云存储的方案,比如说云存储不管你在程序里面做,还是把它挂到宿主机上,让宿主机去做;不管你是用NAS还是用阿里云OSS,把某一个目录挂在本地的一个目录下面,而不用通过SDK或者API再去把你的数据上传到云存储设备。


容器要解决负载均衡等等的问题,这些问题在数据库里面本身已经做好了,不必要去容器化。


应用Docker化交付的过程




开发人员在除了代码 、Config、Test脚本还要写Dockerfile。把这些代码传(Push)到代码仓库,有一个CI service通过代码仓库hook告诉你代码仓库有一个新的提交。把代码拉下来复制,进行两件事情 : Build和UT。在build的过程中,会从Docker Registry上面去拉下来( Pull )依赖的image,当build通过了之后会push image到这个Docker Registry单位里面去。然后CI 会有一个hook去通知CD,deploy Service根据Docker和image描述以及compose描述,把image部署到预发、测试或者生产环境。


整个部署过程就是从Registry里拉下来一份build好的image然后重新run起来。最复杂的东西都集中在image, compose两个描述文件里面,其他东西整个过程都会变得比较简单。


结束语


Docker交付带来什么?




开发可以更清楚更灵活掌握。以前我只关心Java依赖是什么,现在我关心整个的环境依赖是什么;以前我在本地搭一个Java环境非常困难。现在非常容易,运维再也不用因为软件依赖改变自己的时间。不用今天改一个什么配置明天改一个配置。Docker它能够做到什么呢?每人每项目每环境。下一个它是DevOps最好的诠释 : 怎么样把编程用到运维里面,把环境运维以开发思想管理起来,这个才是我认为才是compose的经典。


我们该把什么场景Docker化?




这到今天还没有非常明确的定论。


这是我自己的理解 : 越短生命周期以及越无状态的这种东西,容器化带来最大的好处。比如像web应用,REST API , CI/CD这种,需要跑测试的时候,就把整个Docker容器拉下去去跑,跑完了就扔掉不占有资源了。它是一个任务行为的一个过程,这种场景下用Docker去做,就能节省资源等等非常多的好处。


最不容易Docker化的东西,是数据库,存储这种。容器对这一类并不能带来非常直接的好处。因为假如服务器承载非常强烈的状态下,这就是一个文件存储器。并不是说不能做,意义不大。


关于分享者


唐容


目前负责工程效能团队产品开发工作,主要包含持续交付平台( CRP )及云 Code 平台,在互联网研发团队效率提升和产品交付方面有近 10 年经验。曾负责淘宝日常测试环境,集团源码管理,编译系统等基础设施的建设,以及阿里云云计算等部门的配置管理工作。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
5天前
|
Java 应用服务中间件 Linux
【Docker容器化技术】docker安装与部署、常用命令、容器数据卷、应用部署实战、Dockerfile、服务编排docker-compose、私有仓库
本文主要讲解了Docker的安装与部署、常用命令、容器数据卷、应用部署实战、Dockerfile、服务编排docker-compose、私有仓库以及Docker容器虚拟化与传统虚拟机比较。
【Docker容器化技术】docker安装与部署、常用命令、容器数据卷、应用部署实战、Dockerfile、服务编排docker-compose、私有仓库
|
26天前
|
JSON JavaScript 测试技术
【Docker项目实战】使用Docker部署PPTist在线演示文稿应用
【10月更文挑战第9天】使用Docker部署PPTist在线演示文稿应用
33 1
【Docker项目实战】使用Docker部署PPTist在线演示文稿应用
|
7天前
|
JavaScript 持续交付 Docker
解锁新技能:Docker容器化部署在微服务架构中的应用
【10月更文挑战第29天】在数字化转型中,微服务架构因灵活性和可扩展性成为企业首选。Docker容器化技术为微服务的部署和管理带来革命性变化。本文探讨Docker在微服务架构中的应用,包括隔离性、可移植性、扩展性、版本控制等方面,并提供代码示例。
35 1
|
14天前
|
Kubernetes Cloud Native 开发者
云原生技术入门:Kubernetes和Docker的协作之旅
【10月更文挑战第22天】在数字化转型的浪潮中,云原生技术成为推动企业创新的重要力量。本文旨在通过浅显易懂的语言,引领读者步入云原生的世界,着重介绍Kubernetes和Docker如何携手打造弹性、可扩展的云环境。我们将从基础概念入手,逐步深入到它们在实际场景中的应用,以及如何简化部署和管理过程。文章不仅为初学者提供入门指南,还为有一定基础的开发者提供实践参考,共同探索云原生技术的无限可能。
23 3
|
21天前
|
存储 应用服务中间件 云计算
深入解析:云计算中的容器化技术——Docker实战指南
【10月更文挑战第14天】深入解析:云计算中的容器化技术——Docker实战指南
50 1
|
26天前
|
运维 JavaScript 虚拟化
探索容器化技术:Docker的实践与应用
【10月更文挑战第9天】探索容器化技术:Docker的实践与应用
47 3
|
20天前
|
存储 Kubernetes 监控
深入探索Docker容器化技术的奥秘
【10月更文挑战第15天】深入探索Docker容器化技术的奥秘
17 0
|
21天前
|
运维 Kubernetes 监控
掌握Docker容器化技术:构建、部署与管理的高效实践
【10月更文挑战第14天】掌握Docker容器化技术:构建、部署与管理的高效实践
36 0
|
29天前
|
运维 监控 Cloud Native
深入了解容器化技术:Docker 的应用与实践
【10月更文挑战第6天】深入了解容器化技术:Docker 的应用与实践
38 0
|
29天前
|
云计算 开发者 Docker
揭秘云计算中的容器化技术——Docker的深度解析
【10月更文挑战第6天】揭秘云计算中的容器化技术——Docker的深度解析
下一篇
无影云桌面