使用Jenkins shared library构建docker image

Jenkins

关于CI & CD

CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法。CI/CD 的核心概念是持续集成、持续交付和持续部署。作为一个面向开发和运营团队的解决方案,CI/CD 主要针对在集成新代码时所引发的问题(亦称:“集成地狱”)。

具体而言,CI/CD 在整个应用生命周期内(从集成和测试阶段,到交付和部署)引入了持续自动化和持续监控。这些关联的事务通常被统称为“CI/CD 管道”,由开发和运维团队以敏捷方式协同支持。

关于Jenkins

Jenkins是一款CI/CD工具。Jenkins通过丰富的插件来实现自动化构建、测试和部署软件。

我们可以通过创建Jenkins pipeline的方式来创建一个自动化的流程。通过Jenkins pipeline的定义通常被写入Jenkinsfile中,从而将“简单到复杂”的交付流程实现为“持续交付即代码”。

为什么要用shared library

当下微服务(micro services)大行其道,一个大的项目中可能有许多微服务构成。每个微服务彼此间的构建过程可能非常相识,这样我们每个项目的Jenkinsfile的内容可能有很多重复的代码。每当要修改我们的流程定义的时候,我们就需要逐个项目去修改。

通过shared library我们可以把通用的Jenkins pipeline代码集中起来,存放到外部的源代码版本控制仓库中。当我们的微服务需要使用到shared library的时候只需引入相应的库即可。以下是示例代码:

// 引入shared library: notebook40@0.2.0
// "notebook40"是我们在Jenkins中定义的shared library的名字
// "0.2.0"是shared library的版本。Jenkins会自动匹配版本到源代码控制仓库的branch或tag...
@Library("notebook40@0.2.0") _

// 执行名为commonPipeline的脚本
commonPipeline()

示例

以下是使用shared library的示例。

安装Jenkins

  1. 由于我们需要用Jenkins来构建Docker镜像,最方便的方法是直接在Docker中运行Jenkins。

    docker run -d \
      -u root\
      -p 8080:8080 \
      -v jenkins-data:/var/jenkins_home \
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v /root/.m2:/root/.m2 \
      --name jenkins \
      jenkinsci/blueocean
    
    • -u root使用root用户来运行Jenkins,这样Jenkins就能运行Docker了。
    • -v /var/run/docker.sock:/var/run/docker.sock使Jenkins docker container能访问外部docker。
  2. 安装配置Jenkins用户名密码,并安装推荐的插件。

  3. 安装Pipeline Utility Steps插件。在示例代码中用来读取mavenpom.xml

shared library项目

Shared library用到groovy脚本,以下是shared library项目的详细情况。

  1. shared library项目的默认目录:

    • src目录类似与javasrc,用于存放groovy类文件。
    • vars目录定义可从流水线访问的全局变量的脚本。
    • resources目录允许从外部库中使用jenkins step: libraryResource来加载文本文件。
  2. groovy类中使用jenkins step。

    groovy类中我们不能直接使用Jenkins的step。我们可以通过把当前groovy脚本对象传到groovy中,来允许groovy类调用Jenkins的step。以下代码演示如何在groovy中加载一个properties文件。

    ./vars/commonPipeline.groovy

    import com.notebook40.jenkins.pipeline.Pipelines
    
    // shared library脚本的默认方法。
    // 当Jenkinsfile中调用commonPipeline(当前脚本的文件名字的时候),call方法会被执行。
    def call(Map pipelineParameters) {
      // 参数this把当前脚本对象传给groovy类,使groovy类能调用Jenkins step。
      Pipelines.buildCommonPipeline(this, pipelineParameters)
    }
    

    ./src/.../Pipelines.groovy

    package com.notebook40.jenkins.pipeline
    
    import com.notebook40.jenkins.context.Context
    
    class Pipelines {
      static def buildCommonPipeline(jenkins, Map pipelineParameters) {
        // 用jenkins(commonPipeline的this参数构建Context对象)
        Context context = new Context(jenkins, pipelineParameters)
    
        // 构建Jenkins pipeline
        new DefaultPipelineBuilder().build(context)
      }
    }
    

    ./src/.../DefaultPipelineBuilder.groovy

    void loadProperties(Context context) {
      // 加载一个properties文件
      String propertiesString = context.jenkins.libraryResource(
          "com/notebook40/jenkins/pipeline/defaultPipeline.properties"
      )
    
      // 把properties文件内容加载到Properties对象中
      Properties properties = new Properties()
      properties.load(new StringReader(propertiesString))
    
      // ...
    }
    
  3. 下面是执行maven任务的例子。

    ./src/.../MavenStep.groovy

    package com.notebook40.jenkins.step
    
    import com.notebook40.jenkins.context.Context
    
    abstract class MavenStep extends AbstractStep {
      // 用于执行maven的公用方法
      // context参数用来执行jenkins step和获取运行pipeline的参数
      Closure withMaven(Context context, Closure cl) {
        // 调用withDockerContainer来运行maven镜像
        context.jenkins.withDockerContainer(
            // Maven的镜像名
            "image": mavenImageName(context),
            // 运行Maven镜像的参数
            "args": mavenImageArgs(context)) {
          // 需要执行的内容
          cl()
        }
      }
    
      // ...
    }
    

    ./src/.../PackageStep.groovy

    package com.notebook40.jenkins.step
    
    import com.notebook40.jenkins.context.Context
    
    class PackageStep extends MavenStep {
      @Override
      void process(Context context) {
        // 执行Maven任务
        withMaven(context) {
          // 使用Maven打包项目
          context.jenkins.sh 'mvn -B -DskipTests package'
          context.jenkins.archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
        }
      }
    }
    
  4. 在Jenkins中配置shared library。详情请见:https://jenkins.io/doc/book/pipeline/shared-libraries/

在项目中创建Jenkins文件

  1. ./Jenkinsfile

    @Library("notebook40@0.2.0") _
    
    commonPipeline()
    

创建Jenkins pipeline

  1. 在Jenkins项目中创建pipeline,并运行:
result.jpg

示例代码源码

附录

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容