JenkinsFile完整CI/CD流程实用案例
通过此JenkinsFile实现
拉取->编译->测试->代码质量扫描->docker镜像构建->构建后推送至harbor->部署->清理工作区与通知
ps:Triggers触发器部分待完成后添加
一 环境介绍:
三台虚拟机,Debian12,提前将地址信息写入所有虚拟机/etc/hosts文件
Jenkins: jen.70o70.com,192.168.8.100
harbor: jen.70o70.com,192.168.8.100
Gitlab: git.70o70.com,192.168.8.101
SonarQube: reg.70o70.com,192.168.8.102
Jenkins node: linux.agent,192.168.8.102
二 部署阶段
1、部署Jenkins
# 准备jdk环境
apt install openjdk-17-jdk
# 下载并安装Jenkins.deb包
wget https://mirrors.ustc.edu.cn/jenkins/debian-stable/jenkins_2.504.2_all.deb
dpkg -i jenkins_2.504.2_all.deb
# 运行脚本测试jenkins国内插件源速度
curl -sSL https://cdn.jsdelivr.net/gh/lework/jenkins-update-center/speed-test.sh | bash
# 修改Jenkins插件下载源,没有就新建
vim /var/lib/jenkins/hudson.model.UpdateCenter.xml
<?xml version='1.1' encoding='UTF-8'?>
<sites>
<site>
<id>default</id>
<url>https://mirrors.huaweicloud.com/jenkins/update-center.json</url>
</site>
</sites>
# 删除Jenkins更新缓存
rm -rf /var/lib/jenkins/updates/default.json
2、部署Gitlab
Gitlab较为占用资源,建议最小6G内存
# 请优先参考官网教程
https://gitlab.cn/install/
# 安装依赖
apt install -y curl openssh-server ca-certificates tzdata perl
# 配置软件源
curl -L get.gitlab.cn | bash
# apt安装
apt install -y gitlab-jh
# 修改url
grep ^[^#] /etc/gitlab/gitlab.rb
external_url 'http://git.70o70.com'
# 访问http://git.70o70.com
# 查看默认密码 用户名root
cat /etc/gitlab/initial_root_password
3、部署docker harbor
# 先部署docker环境,这里不再赘述
# github下载离线包
wget https://github.com/goharbor/harbor/releases/download/v2.13.1/harbor-offline-installer-v2.13.1.tgz
# 创建工作目录
mkdir /apps
# 解压
tar xzf harbor-offline-installer-v2.13.0.tgz -C /apps/
cd /apps/harbor/
# 拷贝配置文件模板
cp harbor.yml.tmpl harbor.yml
# 修改hostname,测试环境注释443端口相关,修改admin密码
grep ^[^#] harbor.yml
hostname: jen.70o70.com
http:
port
port: 80
# port: 443
# The path of cert and key files for nginx
# certificate: /your/certificate/path
# private_key: /your/private/key/path
# strong_ssl_ciphers: false
harbor_admin_password: 123456
# 创建一个harbor service文件,方便启停
vim /lib/systemd/system/harbor.service
[Unit]
Description=Harbor Cloud Native Registry
Documentation=https://goharbor.io
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/apps/harbor
ExecStart=/usr/bin/docker compose -f docker-compose.yml up -d
ExecStop=/usr/bin/docker compose -f docker-compose.yml down -v
ExecStopPost=/usr/bin/docker compose -f docker-compose.yml rm -f
[Install]
WantedBy=multi-user.target
# 加载service,设置开机自启
systemctl daemon-reload
systemctl enable --now harbor.service
# docker添加本地仓库http信任,建议所有安装docker的测试节点都添加
cat /etc/docker/daemon.json
{
"insecure-registries": ["jen.70o70.com", "192.168.8.100"]
}
4、部署SonarQube
详见另一篇笔记https://www.cnblogs.com/publichotspot/p/18923197
192.168.8.102虚拟机也作jenkins node使用,需部署将要用到的docker环境
三 添加插件与设置环境
1,Jenkins添加插件
- Docker Pipeline,Docker plugin (流水线调用docker使用)
部署参考https://www.cnblogs.com/publichotspot/p/18923042
Jenkins添加harbor登录凭证,根据路径进入添加

-
webhook(后续触发器使用)
-
Gitlab plugin (调用gitlab使用)
为jenkins创建令牌供调用令牌拉取gitlab仓库内容
进入gitlib->项目->设置->访问令牌->添加新令牌
创建时最小权限原则,选择read_repository只读.角色这里选择Developer

Jenkins添加令牌至全局变量

- config file provider(使用自定maven配置文件)
# 可以使用阿里加速地址
<mirrors>
<mirror>
<id>Aliyun</id>
<mirrorOf>*</mirrorOf>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>

-
DingTalk(钉钉通知)
部署参考https://www.cnblogs.com/publichotspot/p/18925910
2,Jenkins agent配置
部署参考https://www.cnblogs.com/publichotspot/p/18923042
文章内的静态节点部分
# 后台拉起Jenkins agent
nohup java -Xms256m -Xmx256m -jar agent.jar -url http://jen.70o70.com:8080/ -secret 8c465be9b208edf450bd8693145082285c24789a4e43bf2a883d9b8f8004618e -name "linux.agent" -webSocket -workDir "/home/jenkins"
3,docker镜像
将会用到两个docker镜像
# docker 镜像已上传夸克,需要请自取
# 链接:https://pan.quark.cn/s/644355e8a669
# 提取码:QR4R
docker load -i maven:3.9-eclipse-temurin-17-alpine
docker load -i eclipse-temurin:17-jdk-alpine
四 JenkinsFile
点击查看代码
pipeline {
agent none // [1] 在顶层不指定全局agent,让每个阶段按需分配
parameters {
booleanParam(name: 'pushImage', defaultValue: true, description: 'Push Image to Harbor and Deploy?')
}
// 定义环境变量
environment {
// [2] 镜像仓库及项目信息
REGISTRY = 'jen.70o70.com'
PROJECT_NAME = 'spring-boot-helloworld'
IMAGE_URL = "${REGISTRY}/test/${PROJECT_NAME}"
IMAGE_TAG = "${BUILD_ID}"
// [3] SonarQube 服务器配置名称
SONARQUBE_ENV = 'SonarQube'
}
stages {
// =================================================================
// 阶段 1: 在动态的Maven容器中进行编译、测试和代码扫描
// =================================================================
stage('Build, Test & Scan') {
agent {
// [4] 使用一个包含Maven和JDK的Docker镜像作为此阶段的执行环境
docker {
image 'maven:3.9-eclipse-temurin-17-alpine'
label 'linux.agent'
args '--add-host=reg.70o70.com:192.168.8.102'
}
}
steps {
// [5] 拉取代码
git branch: 'main',
credentialsId: 'gitlab-readonly-credential',
url: "http://git.70o70.com/long/spring-boot-helloWorld.git"
// [6] 编译、测试和打包
configFileProvider([configFile(fileId: '702be63f-95f4-481e-aa9e-0a8200e14cae', variable: 'MAVEN_SETTINGS')]) {
sh "mvn -s ${MAVEN_SETTINGS} -B -DskipTests clean package"
sh "mvn -s ${MAVEN_SETTINGS} test"
}
// [7] 执行 SonarQube 扫描
withSonarQubeEnv("${SONARQUBE_ENV}") {
sh 'mvn sonar:sonar'
}
timeout(time: 30, unit: 'MINUTES') {
waitForQualityGate abortPipeline: true
}
// [8] 核心步骤:暂存构建产物
// 将编译好的JAR文件和Dockerfile打包暂存,以便后续阶段使用
echo 'Stashing build artifacts...'
stash includes: 'target/*.jar, Dockerfile', name: 'build-artifacts'
}
}
// =================================================================
// 阶段 2: 在一个专门的Agent节点上制作并推送镜像
// =================================================================
stage('Build & Push Image') {
agent {
// [9] 指定一个专门用于Docker操作的agent节点
label 'linux.agent'
}
steps {
// [10] 核心步骤:取出之前暂存的构建产物
echo 'Unstashing build artifacts...'
unstash 'build-artifacts'
// [11] 使用取出的文件构建镜像
// Dockerfile和JAR文件现在都在当前工作空间中
script {
withCredentials([usernamePassword(
credentialsId: 'a504ce8e-9b2b-41e6-bc02-22c6afd4dd8e',
usernameVariable: 'REG_USER',
passwordVariable: 'REG_PASS'
)]) {
sh "docker login -u ${REG_USER} -p ${REG_PASS} ${REGISTRY}"
sh "docker build -t ${IMAGE_URL}:${IMAGE_TAG} ."
sh "docker push ${IMAGE_URL}:${IMAGE_TAG}"
sh "docker tag ${IMAGE_URL}:${IMAGE_TAG} ${IMAGE_URL}:latest"
sh "docker push ${IMAGE_URL}:latest"
}
}
}
}
stage('Deploy to Docker') {
when { expression { params.pushImage } }
agent { label 'linux.agent' }
steps {
script {
withCredentials([usernamePassword(
credentialsId: 'a504ce8e-9b2b-41e6-bc02-22c6afd4dd8e',
usernameVariable: 'REG_USER',
passwordVariable: 'REG_PASS'
)]) {
sh "docker login -u ${REG_USER} -p ${REG_PASS} ${REGISTRY}"
}
sh "docker stop ${PROJECT_NAME} || true"
sh "docker rm ${PROJECT_NAME} || true"
sh """
docker run -d \\
--name ${PROJECT_NAME} \\
-p 8080:8888 \\
--restart always \\
${IMAGE_URL}:${IMAGE_TAG}
"""
}
}
}
}
// =================================================================
// 构建后操作
// =================================================================
post {
always {
// 在 post 块中,使用 script 块来调用需要 agent 的步骤
script {
// 使用 node 来获取一个 agent 的执行上下文
node('linux.agent') {
echo "Running post-build actions on agent..."
cleanWs()
dingtalk(
robot: 'DingTalkRobot01',
type: 'TEXT',
text: ["构建完成"]
)
}
}
}
}
}
浙公网安备 33010602011771号