1.前言
Hello,各位小伙伴大家好。😄
在上一篇文章【Docker+Jenkins+Gitee自动化部署maven项目】中,咱们详细介绍了如何自动化部署maven项目,如果说你的项目仅仅为maven项目,那么这种部署方式是很契合的,如果我们想要支持更多类型的项目,这种方式就显得有点捉襟见肘了。于是乎,Pipeline流水线任务闪亮登场。如下图所示:
Pipeline流水线任务可以让我们定制整个任务的执行流程,使得其更加的灵活。怎么样,各位小伙伴是不是已经跃跃欲试了。😄
2.Pipeline介绍
这里我们又引入了一个新的概念:Pipeline,没接触过的小伙伴,这时肯定是一脸懵逼了,心中充满了疑问。
- Pipeline是何方神圣?
- Pipeline应该如何使用?
2.1 Pipeline是什么
Pipeline:翻译过来有管道、流水线的意思,简单来说,其定义了一个工作流模型,将原来分布在多个节点的任务组织成一个任务,实现复杂的编排工作。
不知道大家对这个选项还有没有印象,这就是典型的一个大的任务分布在多个小的任务节点上,当一个小的任务执行完成后,通知下一个任务执行。
我们都知道在汽车流水线中,分布着不同的生产单元,每一个生产单元只专注处理各自的分工,Jenkins的Pipeline也有异曲同工之妙。
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"
}
}
}
}
总的来说,声明式语法的结构还是很清晰明了的,主要包含pipeline
、stages
、stage
和steps
块。
-
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项目。
那么就可以总结出部署过程,如下:
- 从Gitee远程仓库拉取代码。
- Maven编译打包。
- Docker构建镜像并运行。
4.准备工作
4.1 添加凭据
第一步就是从Gitee远程仓库拉取代码,因此需要Gitee SSH key。这个之前我们之前已经添加过,这里就不再添加了。具体参照【Docker+Jenkins+Gitee自动化部署maven项目】一文。
4.2 Maven环境变量
第二步是使用Maven对拉取下来的代码编译打包,因此需要配置MAVEN_HOME。前面我们提到过,Jenkins自动安装的Maven环境目录在/var/jenkins_home/tools/
中。
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/
5.Jenkins+Pipeline部署项目
5.1 创建pipeline任务
好了,到这里我们前期的准备工作也做的差不多了,就可以开始创建Pipeline任务了。
定义pipeline脚本。有两种方式:
Pipeline script
:直接在文本界面上定义pipeline脚本。
Pipeline script from SCM
:将pipeline脚本定义在Jenkinsfile中,然后从仓库中拉取,其可以更好地对脚本文件进行版本控制。推荐使用,我这里也是使用的这种方式。
5.2 手动部署
点击立即构建,出现以下界面,表示任务执行成功。由于我是使用虚拟机搭建的服务器,上篇文章我们介绍了ngrok外网映射的方式来实现WebHook触发自动构建,这里就不再介绍了。
6.总结
如果看过【Docker+Jenkins+Gitee自动化部署maven项目】文章小伙伴,对比Pipeline流水线任务,或许会觉得直接创建构建maven任务还更加滴简单,是的,我此刻也有这种感受。
不过,那种方式只适用于maven单模块项目,如果是微服务项目或者其他语言的项目,就无能为力了。
我们这里也只算是简单的介绍了Pipeline流水线任务的用法,后续会继续探索。