文档章节

使用Maven和Docker进行持续交付中的版本号管理

 风摆残荷
发布于 2017/02/14 21:59
字数 2221
阅读 250
收藏 3
点赞 0
评论 0

动机

我们来思考下持续交付的原则。

  • 每次构建的结果可能是一个潜在的发行版本
  • 消除手动瓶颈
  • 尽可能自动化

这三点正是我们想要实现的,但是在实现之前,我们先来看下在典型的Maven发布流程和经典方式版本号管理上的具体问题。

没有自动化

通常来说,一次提交会触发一个快照构建,然后生成一个快照构件(“8.1.2-SNAPSHOP”)。当开发者感觉软件到达稳定状态后,他会触发一次专用发布构建。因此,他预先分配版本号(“8.2.0”)

A human has to assign a version number and trigger the release build.

人员必须分配版本号然后触发发布构建

这种方式有什么缺点:

  • 我们需要手动触发专用的发布工作流程
  • 版本号需要人为手动分配
  • 此外,仅看版本号“8.2.0”并不清晰,比如这个版本号的构件中包含了哪些提交(代码)。我们需要一个Git标签

任意快照

此外,快照引起了许多问题。

Unclear and changing content of snapshot artifacts.

不清晰的内容变动

  • 不可追踪。我们不能说,有哪些提交包含在了当前的快照构件中。
  • 不可靠。快照构件可以很快速的修改。这样很容易引起问题
  • 易出错。不过不注意,很容易覆盖一个快照(比如:当创建Git分支的时候,忘记修改POM文件中的版本号。从Git分支上构建会覆盖之前的快照)

让人生气的Maven发布插件

最后,Maven的发布插件也引起了许多问题:

  • 开销。Maven发布插件运行3次完整的构件和测试周期,展开POM文件两次和创建三次Git修订(Git revisions)
  • 不具有隔离性。当其他人在发布版本期间提交更改时,插件可能容易陷入混乱。
  • 不具有原子性。如果最后一步出现问题(比如:在构件上传期间),突然发现紧急Bug。我们必须清理创建的Git标签,Git修订和修复错误版本

解决方案:利用Git提交哈希

我们使用Git提交哈希来作为构件的版本号

Using the Git commit hash as the version number.

使用Git提交哈希作为版本号

  • 每个构建都incident,有一个机器分配的唯一号码
  • 因此,每个构件都是潜在可交付的。所以这里不需要一个专用的发布流程
  • => 交付管道大大简化和自动化
  • 可追踪。这很明显,哪些提交被包含到构件中。
  • 重复性。只需检出版本并再次进行构建构件(假设没有快照依赖)。
  • 基本上,Git标签不再需要了。

实现

让我们在Maven构建中集成版本命名。下面的事例构建生成一个简单的Spring Boot服务作为Fat Jar。此外,我们把Fat Jar包装到Docker镜像中,并部署镜像。完整的源码可以在GitHub中查看。

为了增加人的可读性,我们把时间戳作为Git提交哈希的前缀。因此,我们的版本号如下所示:

format:  yyyyMMdd-HHmmss.abbreviatedCommitHash
example: 20160702-152019.75c54f5

使用Git提交哈希作为版本号

这是最重要的一步,我们使用 git-commit-id-plugin 。这个插件可以从.git目录读取Git提交哈希和提交时间戳,并可以在POM中可以使用Maven属性使用。

<plugin>
    <groupId>pl.project13.maven</groupId>
    <artifactId>git-commit-id-plugin</artifactId>
    <version>2.2.1</version>
    <executions>
        <execution>
            <phase>validate</phase>
            <goals>
                <goal>revision</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <dateFormat>yyyyMMdd-HHmmss</dateFormat><!--  human-readable part of the version number -->
        <dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
        <generateGitPropertiesFile>false</generateGitPropertiesFile><!-- somehow necessary. otherwise the variables are not available in the pom -->
    </configuration>
</plugin>

下一步,我们可以在Maven属性中添加包含了Git提交哈希和提交时间戳的版本号属性。

<properties>
   <version.number>${git.commit.time}.${git.commit.id.abbrev}</version.number>
</properties>

现在,我们可以在version标签中使用这个属性。

<groupId>de.philipphauer.blog</groupId>
<artifactId>versioning-continuous-delivery</artifactId>
<version>${version.number}</version>

使用方式:

> mvn package # creates the jar with the desired version number
> java -jar target/versioning-continuous-delivery-20160702-180249.193a613.jar # starts the service

使用版本号创建、标记Docker镜像

我们使用 io.fabric8 的docker-maven-plugin来创建镜像。重要的部分是标签。我们创建两个标签。一个标签以提交ID命名(“20160702-153902.7c12eb”),另一个以“latest”命名。latest标签将会简化本地测试。

<plugin>
    <groupId>io.fabric8</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.15.9</version>
    <extensions>true</extensions>
    <configuration>
        <authConfig> <!-- or use "docker login" up front to store the credentials on the local machine. -->
            <username>phauer</username>
            <password>docker123</password>
        </authConfig>
        <images>
            <image>
                <name>${docker.repository.name}:${version.number}</name>
                <alias>${project.artifactId}</alias>
                <build>
                    <from>anapsix/alpine-java:jre8</from>
                    <tags><!-- define additional tags for the image -->
                        <tag>latest</tag>
                    </tags>
                    <assembly>
                        <descriptor>assembly.xml</descriptor>
                    </assembly>
                    <ports>
                        <port>8080</port>
                    </ports>
                    <cmd>
                        <shell>
                            java -jar /maven/${project.artifactId}-${version.number}.jar
                        </shell>
                    </cmd>
                </build>
            </image>
        </images>
    </configuration>
    <executions>
        <execution>
            <id>build-docker-image</id>
            <phase>package</phase>
            <goals>
                <goal>build</goal>
            </goals>
        </execution>
        <execution>
            <id>push-docker-image-to-registry</id>
            <phase>deploy</phase>
            <goals>
                <goal>push</goal>
            </goals>
        </execution>
    </executions>
</plugin>

不要忘记assembly.xml和如下的属性:

<docker.repository.name>phauer/${project.artifactId}</docker.repository.name>

用法:

> mvn package # creates a docker image and installs it to the local repository

> docker images
REPOSITORY                                                TAG                              IMAGE ID            CREATED             SIZE
phauer/versioning-continuous-delivery                     20160702-174649.28b5299          12d7a526c506        2 seconds ago       135.8 MB
phauer/versioning-continuous-delivery                     latest                           12d7a526c506        2 seconds ago       135.8 MB

> docker-compose up # starts the local image with the tag "latest"

> mvn deploy # pushes the image to the docker registry

完整的pom.xmldocker-compose.yml可以在GitHub中查看。

开放问题和讨论

部署构件的Git标签

有时,在真正部署的时候,使用专用的Git标签来标记一个构件是非常方便的。你可以在部署后自由标记相应的Git修订版本。你可以手动执行此操作,也可以在最终的deploy流程中集成。后者使工作流程自动化。

构件泛滥问题的处理

每次构建都会带出一个新的构件,我们在我们的存储库中面临着大量的构件。因此,我们必须清理:

  • 但是我们怎么知道已经部署了哪些版本?我们不想删除当前正在生产环境的构件。因此,我们必须维护已部署的版本列表,并在清理期间跳过他们。我们可以通过使用Git标签来实现此目的,即当构件部署的时候,我们创建一个Git标签。我们也可以在任意地方保存版本号列表。
  • 说实话,删除曾经是生产中的构件没有问题。你曾回滚到一年前的构件过吗?通常来说,你只需要当前部署的构件和它之前几个。

检查快照依赖关系

当发现快照依赖时,maven-release-plugin会中止构建。这基本上没问题,因为快照依赖阻止了构建的可重复性。我们缺乏这种检查。但是,我认为这在实践中不是什么大问题。

  • 这很少发生。通常开发人员在发布快照依赖之前会注意并删除快照依赖。
  • 当我们对我们的库应用建议的版本号概念时,我们根本没有快照。
  • 即使我们的构件包含快照,快照仍然捆绑在构件(fat jar或者Docker镜像)中。构件保存在注册表中,然后测试到最终发布。如果我们在我们的注册表中有构建的构件,我们真的需要重复构建吗?

使用构建时间戳替换Git提交哈希

有一种版本方式是使用构建的时间戳来替换提交哈希。因为下面的原因,我更倾向于提交哈希:

  • 显示的跟踪版本号提交
  • 基本上不需要Git标签
  • 基于给定修订,可在现构件

Docker是此版本控制方法所必须的吗?

基本上不是。如果你的Maven构建只生成一个jar,也可以应用建议的方法。在这种情况下,我们还是使用Git提交哈希作为Jar的版本号。

但是,有一个问题,有git-commit-id-plugin插件创建的默认属性不会被maven-install-plugin和maven-deploy-plugin插件解析到。这里有一个解决方案。

此外,Docker让事情变得更简单。Maven只允许一个构件只能有一个版本号。Docker允许一个镜像有多个标签。你可以使用“7d1dcc”和“latest”共同标记一个镜像。latest对于本地测试非常有用。你可以一直使用latest镜像,而不是永远的提升版本号(比如在本地docker-compose.yml中)

 

----------------------------------------------------------------------------------------------------

原文:https://blog.philipphauer.de/version-numbers-continuous-delivery-maven-docker/

© 著作权归作者所有

共有 人打赏支持
粉丝 2
博文 11
码字总数 25536
作品 0
昌平
程序员
我们应该如何基于容器来进行软件的持续交付(一)?

概述 在过去的一段时间里容器已经大量的使用到了IT软件生产的各个环节当中:从软件开发,持续集成,持续部署,测试环境到生产环境。 除了Docker官方的Docker Swarm, Docker Machine以及Docke...

wise2c ⋅ 2016/12/22 ⋅ 0

50+ 最棒的 DevOps 开源工具

你喜欢免费的东西吗?获得开发者社区支持的自动化,开源的工具是大家梦寐以求的。这里列举了 50+ 款最棒的开源工具,可以帮助你很好的实行 DevOps。 大图请点击这里。 开发工具 版本控制&协作...

OSC编辑部 ⋅ 2015/08/10 ⋅ 1

jenkins笔记(1)

一、相关概念 > ## 1.1 Jenkins概念: Jenkins是一个功能强大的应用程序,允许持续集成和持续交付项目,无论用的是什么平台。这是一个免费的源代码,可以处理任何类型的构建或持续集成。集成...

KaliArch ⋅ 2017/12/14 ⋅ 0

我们应该如何基于容器来进行软件的持续交付(二)?

概述 接着上一篇的内容,我们有讲到“持续交付是文化,自动化是基石,垮职能团队协作是根本”,本文将以软文的形式介绍持续交付平台WiseBuild结合Rancher容器管理平台我们是如何进行跨职能团...

wise2c ⋅ 2016/12/26 ⋅ 0

60 个 DevOps 开源工具,你在用哪些?

原文出处:Mrina Natarajan 译文出处:开源中国 你喜欢免费的东西吗?获得开发者社区支持的自动化,开源的工具是大家梦寐以求的。这里列举了 60 多款最棒的开源工具,可以帮助你很好的实行 De...

Mrina Natarajan ⋅ 2016/03/17 ⋅ 0

生活不止有苟且,还有N个免费DevOps开源工具

你喜欢免费的东西吗?获得开发者社区支持的自动化,开源的工具是大家梦寐以求的。这里列举了 N多款最棒的开源工具,可以帮助你很好的实行 DevOps。对的,生活不止有眼前的苟且,还有诗和远方的...

oschina ⋅ 2016/04/04 ⋅ 21

N 个免费 DevOps 开源工具,没用过,至少应该了解!

在介绍Devops工具之前,先跟随码花来了解下:Devops是个啥? Devops=【Development】+【Operations】。 简言之,Devops主要用于开发、测试、运维之间的沟通、协作与整合,减少开发和运营之间...

oschina ⋅ 2016/05/20 ⋅ 20

欢迎来试用我们的开源项目 Cyclon

Hi , Caicloud 宣布开源其 CI/CD 平台 Cyclone,专注解决微服务架构下面向容器的 CI/CD 和版本管理问题。 Cyclone 项目是基于 K8S 的第一个 CI/CD 工具,完善了 K8S 生态圈。 Cyclone 在 Gi...

Caicloud ⋅ 2016/11/14 ⋅ 0

在Maven中如何恰当的管理版本

目前在JAVA的世界中,maven已经成为事实上的构建标准,很多开源库的管理构建也是基于maven的,maven本身的学习曲线比较陡峭,遵循“约定优于配置”的理念,maven存在很多约定。本次我先描述下...

码代码的小司机 ⋅ 04/16 ⋅ 0

不可错过的「持续集成」进阶指南

随着软件部署的越来越成熟,敏捷、DevOps、CI/CD、Docker 等词语慢慢出现在工程师的视野中。对于持续集成,业界也没有一个通用的模式,每个团队可能习惯的方式和关注点都不一样。持续集成最关...

风起云飞fir_im ⋅ 2016/10/28 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

mysql5.7系列修改root默认密码

操作系统为centos7 64 1、修改 /etc/my.cnf,在 [mysqld] 小节下添加一行:skip-grant-tables=1 这一行配置让 mysqld 启动时不对密码进行验证 2、重启 mysqld 服务:systemctl restart mysql...

sskill ⋅ 昨天 ⋅ 0

Intellij IDEA神器常用技巧六-Debug详解

在调试代码的时候,你的项目得debug模式启动,也就是点那个绿色的甲虫启动服务器,然后,就可以在代码里面断点调试啦。下面不要在意,这个快捷键具体是啥,因为,这个keymap是可以自己配置的...

Mkeeper ⋅ 昨天 ⋅ 0

zip压缩工具、tar打包、打包并压缩

zip 支持压缩目录 1.在/tmp/目录下创建目录(study_zip)及文件 root@yolks1 study_zip]# !treetree 11└── 2 └── 3 └── test_zip.txt2 directories, 1 file 2.yum...

蛋黄Yolks ⋅ 昨天 ⋅ 0

聊聊HystrixThreadPool

序 本文主要研究一下HystrixThreadPool HystrixThreadPool hystrix-core-1.5.12-sources.jar!/com/netflix/hystrix/HystrixThreadPool.java /** * ThreadPool used to executed {@link Hys......

go4it ⋅ 昨天 ⋅ 0

容器之上传镜像到Docker hub

Docker hub在国内可以访问,首先要创建一个账号,这个后面会用到,我是用126邮箱注册的。 1. docker login List-1 Username不能使用你注册的邮箱,要用使用注册时用的username;要输入密码 ...

汉斯-冯-拉特 ⋅ 昨天 ⋅ 0

SpringBoot简单使用ehcache

1,SpringBoot版本 2.0.3.RELEASE ①,pom.xml <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.3.RELE......

暗中观察 ⋅ 昨天 ⋅ 0

监控各项服务

比如有三个服务, 为了减少故障时间,增加监控任务,使用linux的 crontab 实现. 步骤: 1,每个服务写一个ping接口 监控如下内容: 1,HouseServer 是否正常运行,所以需要增加一个ping的接口 ; http...

黄威 ⋅ 昨天 ⋅ 0

Spring源码解析(八)——实例创建(下)

前言 来到实例创建的最后一节,前面已经将一个实例通过不同方式(工厂方法、构造器注入、默认构造器)给创建出来了,下面我们要对创建出来的实例进行一些“加工”处理。 源码解读 回顾下之前...

MarvelCode ⋅ 昨天 ⋅ 0

nodejs __proto__跟prototype

前言 nodejs中完全没有class的这个概念,这点跟PHP,JAVA等面向对象的语言很不一样,没有class跟object的区分,那么nodejs是怎么样实现继承的呢? 对象 对象是由属性跟方法组成的一个东西,就...

Ai5tbb ⋅ 昨天 ⋅ 0

Ubuntu16.04 PHP7.0 不能用MYSQLi方式连接MySQL5.7数据库

Q: Ubuntu16.04 PHP7.0 不能用MYSQLi方式连接MySQL5.7数据库 A: 执行以下2条命令解决: apt-get install php-mysql service apache2 restart php -m 执行后会多以下4个模块: mysqli mysqlnd...

SamXIAO ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部