gitleb Android GitLab 流水线 gitee 流水线_jar

1.前言

Hello,各位小伙伴大家好。😄

在上一篇文章【Docker+Jenkins+Gitee自动化部署maven项目】中,咱们详细介绍了如何自动化部署maven项目,如果说你的项目仅仅为maven项目,那么这种部署方式是很契合的,如果我们想要支持更多类型的项目,这种方式就显得有点捉襟见肘了。于是乎,Pipeline流水线任务闪亮登场。如下图所示:

gitleb Android GitLab 流水线 gitee 流水线_Jenkins_02

Pipeline流水线任务可以让我们定制整个任务的执行流程,使得其更加的灵活。怎么样,各位小伙伴是不是已经跃跃欲试了。😄

2.Pipeline介绍

这里我们又引入了一个新的概念:Pipeline,没接触过的小伙伴,这时肯定是一脸懵逼了,心中充满了疑问。

  • Pipeline是何方神圣?
  • Pipeline应该如何使用?

2.1 Pipeline是什么

Pipeline:翻译过来有管道、流水线的意思,简单来说,其定义了一个工作流模型,将原来分布在多个节点的任务组织成一个任务,实现复杂的编排工作。

gitleb Android GitLab 流水线 gitee 流水线_jenkins_03

不知道大家对这个选项还有没有印象,这就是典型的一个大的任务分布在多个小的任务节点上,当一个小的任务执行完成后,通知下一个任务执行。

我们都知道在汽车流水线中,分布着不同的生产单元,每一个生产单元只专注处理各自的分工,Jenkins的Pipeline也有异曲同工之妙。

gitleb Android GitLab 流水线 gitee 流水线_jar_04

2.2 如何使用Pipeline

到这里,相信大家心中对Pipeline的定义已经有一定的理解了,现在要看的就是如何来使用它了。

创建一个Pipeline任务需要我们提供一个Pipeline脚本,其基于Groovy语法。

Pipeline脚本支持两种语法:声明式(Declarative)语法和脚本式(Scripted)语法。

2.2.1 声明式(Declarative)语法

先来看个最简单的示例:

pipeline {
    agent any
    stages {
        stage('git pull') {
            steps {
                echo "git pull"
            }
        }
        stage('mvn package'){
            steps{
                echo "mvn package"
            }
        }
        stage('deploy'){
            steps{
                echo "deploy"
            }
        }
    }
}

总的来说,声明式语法的结构还是很清晰明了的,主要包含pipelinestagesstagesteps块。

  • pipeline:见名知意,用来定义一个Pipeline。
  • stage:用来定义Pipeline的一个阶段,需定义在stages块中。
  • steps:用来定义一个阶段中存在的步骤,例如各种shell命令。

2.2.2 脚本式(Scripted)语法

node {
    stage('deploy'){
        steps{
            echo "deploy"
        }
    }
    stage('mvn package'){
        steps{
            echo "mvn package"
        }
    }
    stage('deploy'){
        steps{
            echo "deploy"
        }
    }
}
  • node:含义同声明式语法的pipeline,用来定义一个Pipeline
  • stage:用来定义Pipeline的一个阶段。
  • steps:用来定义一个阶段中存在的步骤,例如各种shell命令。

相比声明式语法,脚本式语法的层次结构没有那么清晰,因此,Jenkins推荐使用声明式语法

3.构建过程

先来看看我这里准备的项目,一个简单的SpringBoot项目。

gitleb Android GitLab 流水线 gitee 流水线_jenkins_05

那么就可以总结出部署过程,如下:

  • 从Gitee远程仓库拉取代码。
  • Maven编译打包。
  • Docker构建镜像并运行。

4.准备工作

4.1 添加凭据

第一步就是从Gitee远程仓库拉取代码,因此需要Gitee SSH key。这个之前我们之前已经添加过,这里就不再添加了。具体参照【Docker+Jenkins+Gitee自动化部署maven项目】一文。

gitleb Android GitLab 流水线 gitee 流水线_docker_06

4.2 Maven环境变量

第二步是使用Maven对拉取下来的代码编译打包,因此需要配置MAVEN_HOME。前面我们提到过,Jenkins自动安装的Maven环境目录在/var/jenkins_home/tools/中。

gitleb Android GitLab 流水线 gitee 流水线_docker_07

4.3 构建镜像并运行

第三步Docker构建镜像并运行,这里我准备了Dockerfile和deploy.sh脚本。

Dockerfile

# 指定基础镜像,这是分阶段构建的前期阶段
FROM openjdk:11-jre   as builder
# 执行工作目录
WORKDIR apps
# 配置参数
ARG JAR_FILE=target/*.jar
# 将编译构建得到的jar文件复制到镜像空间中
COPY ${JAR_FILE} application.jar
# 通过工具spring-boot-jarmode-layertools从application.jar中提取拆分后的构建结果
RUN java -Djarmode=layertools -jar application.jar extract

# 正式构建镜像
FROM openjdk:11-jre
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
WORKDIR apps
# 前一阶段从jar中提取除了多个文件,这里分别执行COPY命令复制到镜像空间中,每次COPY都是一个layer
COPY --from=builder apps/dependencies/ ./
COPY --from=builder apps/spring-boot-loader/ ./
COPY --from=builder apps/snapshot-dependencies/ ./
COPY --from=builder apps/application/ ./
ENTRYPOINT java ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher

deploy.sh

#!/bin/bash
# 服务名称
SERVER_NAME=$1
# 镜像tag
IMAGE_TAG=$2
# 镜像名称
IMAGE_NAME=$SERVER_NAME:$IMAGE_TAG
echo "------ 开始构建镜像:${SERVER_NAME} ------"
docker build -t ${IMAGE_NAME} .
echo "------ 镜像构建结束:${IMAGE_NAME} ------"
if [[ -n $(docker ps -q -f "name=^${SERVER_NAME}$") ]];then
    echo "------ 容器正在运行:${SERVER_NAME} ------"
    echo "------ 停止容器:$SERVER_NAME ------"
    docker stop $SERVER_NAME
    echo "------ 删除容器:$SERVER_NAME ------"
    docker rm $SERVER_NAME
else
    echo "------ 容器未在运行:${SERVER_NAME} ------"
    echo "------ 删除容器:$SERVER_NAME ------"
    docker rm $SERVER_NAME
fi

echo "------ 开始运行容器:$SERVER_NAME ------"
docker run -d --name $SERVER_NAME -p 9090:9090 ${IMAGE_NAME}
echo "------ 清理虚悬镜像 ------"
if [[ -n $(docker images | grep "none" | awk '{print $3}') ]];then
    docker rmi -f $(docker images | grep "none" | awk '{print $3}')
fi

4.4 pipeline脚本

最后的最后,我们需要把前面3个步骤整合一个Pipeline脚本中,这也是Pipeline流水线任务的优势所在。

pipeline {
    agent any
    stages {
        // 拉取代码
        stage('git pull') {
            steps {
                git credentialsId: 'c6adcee5-a169-466a-88ce-9f1eaf0eabbb', url: 'xx/jenkins-test.git'
            }
        }
        // 编译打包
        stage('mvn package'){
            steps{
                sh 'mvn clean package -Dmaven.test.skip=true'
            }
        }
        // 构建docker镜像并运行,${JOB_NAME}为Jenkins内置变量
        stage('deploy'){
            steps{
                sh 'bash /var/jenkins_home/sh/deploy.sh ${JOB_NAME} master'
            }
        }
    }
}

可能这里各位小伙伴有些疑惑,拉取代码的脚本怎么是这样的?

git credentialsId: 'c6adcee5-a169-466a-88ce-9f1eaf0eabbb', url: 'xx/jenkins-test.git'

其实这里使用了Jenkins提供的片段生成器,访问地址为YOUR_JENKINS_URL/pipeline-syntax,例如我这里就是http://192.168.110.101:8080/pipeline-syntax/

gitleb Android GitLab 流水线 gitee 流水线_docker_08

5.Jenkins+Pipeline部署项目

5.1 创建pipeline任务

好了,到这里我们前期的准备工作也做的差不多了,就可以开始创建Pipeline任务了。

gitleb Android GitLab 流水线 gitee 流水线_docker_09

定义pipeline脚本。有两种方式:

Pipeline script:直接在文本界面上定义pipeline脚本。

Pipeline script from SCM:将pipeline脚本定义在Jenkinsfile中,然后从仓库中拉取,其可以更好地对脚本文件进行版本控制。推荐使用,我这里也是使用的这种方式。

gitleb Android GitLab 流水线 gitee 流水线_jar_10

gitleb Android GitLab 流水线 gitee 流水线_docker_11

5.2 手动部署

点击立即构建,出现以下界面,表示任务执行成功。由于我是使用虚拟机搭建的服务器,上篇文章我们介绍了ngrok外网映射的方式来实现WebHook触发自动构建,这里就不再介绍了。

gitleb Android GitLab 流水线 gitee 流水线_docker_12

6.总结

如果看过【Docker+Jenkins+Gitee自动化部署maven项目】文章小伙伴,对比Pipeline流水线任务,或许会觉得直接创建构建maven任务还更加滴简单,是的,我此刻也有这种感受。

不过,那种方式只适用于maven单模块项目,如果是微服务项目或者其他语言的项目,就无能为力了。

我们这里也只算是简单的介绍了Pipeline流水线任务的用法,后续会继续探索。