CI/CD——在jenkins中使用pipeline方式自动化构建java项目jpress

CI/CD------在jenkins中自动化构建与部署java项目jpress的镜像且搭建一键部署gitlab与jenkins环境https://coffeemilk.blog.csdn.net/article/details/160831483?spm=1001.2014.3001.5502

一、jenkins pipeline简介

1.1、pipeline是什么

Jenkins Pipeline 是 Jenkins 2.0+ 核心的 流水线即代码(Pipeline as Code) 插件套装,用代码(Groovy DSL)定义从代码提交到部署的完整 CI/CD 流程,脚本统一存放在 Jenkinsfile 并纳入 Git/SVN 版本管理【Jenkins Pipeline 是 CI/CD 的 "操作系统",把零散的交付步骤变成可复用、可追溯、可管控的代码化流水线,特别适合中大型项目、微服务、多环境、企业级合规场景,是 DevOps 落地的核心工具】。

简单的说: Pipeline是一套运行在 Jenkins 上的工作流框架,将原来独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排和可视化的工作。

Jenkins Pipeline有两种写法【声明式】与【脚本式】:

声明式(Declarative)【✅ 首选推荐】 脚本式(Scripted)
固定语法、配置化、写流程,像「配置文件」,小白也能看懂,企业 90% 项目首选 原生 Groovy 代码、编程化、写逻辑,像「写程序」,适合复杂分支、循环、自定义复杂逻辑
* 基于 Jenkins 预定义 DSL 语法,不是纯自由 Groovy * 语法强约束:固定关键字、固定层级结构,写错直接报错 * 设计初衷:标准化、统一流程、降低学习成本、适合团队规范 * 文件后缀:Jenkinsfile 标准写法 * 基于 原生 Groovy 脚本,就是在 Jenkins 里跑 Groovy 代码 * 无强制结构:可以随便写 if/else、for 循环、函数、类、异常捕获 * 设计初衷:极致灵活,解决声明式搞不定的复杂业务逻辑 * 早期 Jenkins Pipeline 唯一写法,现在逐步被声明式替代
✅ 特点: * 结构整齐划一,所有人的流水线长得都差不多 * 不用会 Groovy 编程,照着模板改就行 * 内置:超时、重试、并行、环境变量、post 生命周期,开箱即用 ✅ 特点: * 完全编程思维:if/else、for、while、函数、类、try-catch 随便用 * 没有强制格式,想怎么写就怎么写 * 老运维 / 开发上手快,但每个人写法都不一样,难以标准化

jenkins pipeline的日常使用总结:

  • 日常业务、团队标准化、新手入门 → 无脑用 声明式
  • 超复杂编程逻辑、动态编排、老项目维护 → 才用 脚本式
  • 实际工作:声明式为主,script 内嵌脚本式为辅 是行业通用最佳方案。

1.2、pipeline有啥用

Pipeline的核心价值 说明
流程代码化、可追溯 流水线逻辑写在 Jenkinsfile 里,随代码一起版本控制,可评审、可回滚、可审计,告别 FreeStyle 零散配置Jenkins
全流程自动化(CI/CD 落地) 一键串联:拉代码 → 编译 / 构建 → 单元测试 → 代码扫描 → 打包 → 镜像构建 → 环境部署 → 冒烟测试 → 生产发布,减少人工干预与错误。
可视化与可观测 阶段视图直观展示各环节状态、耗时、日志;支持失败重试、断点续跑、超时 / 异常处理。
复杂流程编排能力强 * 并行执行(如多模块同时构建、多环境并行测试)。 * 条件分支(不同分支 / 环境走不同流程)。 * 人工审批(如生产发布前卡点确认)。 * 跨节点 / 容器调度(Agent 分配、Docker 化构建)。
复用与标准化 支持共享库(Shared Library),通用逻辑封装复用;团队统一 Jenkinsfile 模板,规范交付流程。

1.3、pipeline的适用场景

pipeline的适用场景 说明
标准 CI/CD 流程(最常用) * 场景:Web 应用、后端服务、移动端、前端项目。 * 流程:代码提交 → 自动构建 → 自动化测试 → 部署到开发 / 测试 / 生产环境。 * 优势:一键发布、质量卡点、全链路追溯
微服务 / 多模块项目 * 场景:几十 / 上百个微服务,依赖复杂、发布频繁。 * 能力:并行构建、依赖编排、批量部署、统一版本管理。
多环境与复杂发布 * 场景:开发 → 测试 → 预发 → 生产,多集群 / 多机房部署。 * 能力:环境隔离、配置区分、灰度发布、回滚机制、生产审批卡点。
基础设施即代码(IaC) * 场景:K8s 资源编排、Docker 镜像构建、云资源(AWS / 阿里云)创建。 * 能力:与 Kubernetes、Terraform、Ansible 集成,实现环境自动化创建与销毁
企业级规范与合规 * 场景:金融、政企等对流程合规、审计、权限控制要求高。 * 能力:流程固化、操作留痕、审批链、权限分级,满足等保 / 合规审计要求。

注意:pipeline不适合【超简单项目(仅单步编译 / 打包,无测试 / 部署)】、【临时一次性任务(用 FreeStyle 更轻量)】。

1.4、pipeline的核心概念

pipeline的核心概念 说明
Node(节点) 一个 Node 就是一个 Jenkins 节点,Master 或者 Agent,是执行 Step 的具体运行环境。
Stage(阶段) 一个 Pipeline 可以划分为若干个 Stage,每个 Stage 代表一组操作(如:Build、Test、Deploy,Stage 是一个逻辑分组的概念,可以跨多个 Node)
Step(步骤) Step是最基本的操作单元,可以是打印一句话,也可以是构建一个 Docker 镜像,由各类 Jenkins 插件提供(如命令:sh 'make',就相当于我们平时 shell 终端中执行 make 命令一样)。

1.5、pipeline的使用

Pipeline 也有两种创建方法:【可以直接在 Jenkins 的 Web UI 界面中输入脚本】;【也可以通过创建一个 Jenkinsfile 脚本文件放入项目源码库中】。

推荐在 Jenkins 中直接从源代码控制(SCMD)中直接载入 Jenkinsfile Pipeline 这种方法,本文为了更直观的展示,直接在 Web UI 界面中输入脚本。

二、pipeline示例

登录到jenkins的web管理后台,然后点击左上角的【+ 新建Item】输入一个任务名称,然后选择pipeline流水线,然后在【pipeline script】下添加上如下的示例内容即可。

2.1、pipeline的基础示例

bash 复制代码
node {
  stage('Clone') {
    echo "1.Clone Stage"
  }
  stage('Test') {
    echo "2.Test Stage"
  }
  stage('Build') {
    echo "3.Build Stage"
  }
  stage('Deploy') {
    echo "4. Deploy Stage"
  }
}

2.3、声明式为主+内嵌script内嵌脚本示例

最佳写法规范:

  1. 95% 流程 用标准声明式结构
  2. 但凡要循环、遍历、复杂 if、动态逻辑 全部包进 script {}
  3. 绝不单独写老式纯脚本式流水线,维护成本极高
bash 复制代码
pipeline {
    // 运行在任意可用Agent节点
    agent any

    // 全局环境变量
    environment {
        // 项目名、版本、仓库地址自行改
        PROJECT_NAME = "ops/jpress"
        GIT_URL      = "git@gitlab2.ck.com:ops/jpress.git"
        // 从Jenkins全局配置拿凭证
        DOCKER_REGISTRY = "gitlab2.ck.com:5050"
    }

    // 流水线全局配置
    options {
        timeout(time: 1, unit: 'HOURS')  // 整体流水线1小时超时
        buildDiscarder(logRotator(numToKeepStr: '10')) // 只保留最近10条构建记录
        retry(count: 1)  // 失败自动重试1次
    }

    // 流水线阶段
    stages {
        stage('1. 拉取代码') {
            steps {
                echo "开始拉取代码:${GIT_URL}"
                git url: "${GIT_URL}", branch: 'master'
            }
        }

        stage('2. 编译打包') {
            steps {
                sh '''
                    export JAVA_HOME=/data/openjdk17
                    export PATH=$JAVA_HOME/bin:$PATH
                    /usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true
                '''
            }
        }

        stage('3. 代码质量扫描') {
            steps {
                sh 'mvn sonar:sonar'
            }
            // 只有master分支才做代码扫描,其他分支跳过
            when {
                branch 'master'
            }
        }

        stage('4. 复杂自定义逻辑(内嵌Script)') {
            steps {
                // 声明式里嵌脚本式Groovy,写复杂循环、判断、遍历
                script {
                    // 定义环境列表
                    def envList = ['dev', 'pre', 'master']
                    echo "遍历所有待部署环境:"

                    // 循环遍历
                    for (env in envList) {
                        echo "当前处理环境:${env}"
                    }

                    // 复杂if-else逻辑
                    def branchName = env.BRANCH_NAME
                    if (branchName == 'master') {
                        echo "主线程:准备预发/生产部署流程"
                    } else if (branchName.startsWith('feature/')) {
                        echo "功能分支:只部署开发环境"
                    } else {
                        echo "其他分支:仅编译不部署"
                    }
                }
            }
        }

        stage('5. 并行构建多任务') {
            steps {
                // 声明式原生并行,不用自己写循环
                parallel(
                    "构建镜像": { sh 'docker build -t ${DOCKER_REGISTRY}/${PROJECT_NAME}:${BUILD_NUMBER} .' },
                    "推送镜像": { sh 'docker push ${DOCKER_REGISTRY}/${PROJECT_NAME}:${BUILD_NUMBER}' }
                )
            }
        }

        stage('6. 部署到开发环境') {
            when {
                branch 'master'
            }
            steps {
                sh 'echo 执行K8s/服务器部署命令...'
            }
        }

        stage('7. 生产发布人工审批') {
            when {
                branch 'master'
            }
            steps {
                // 人工卡点确认,不点不往下走
                input message: '确认是否发布到生产环境?', ok: '确认发布'
                sh 'echo 执行生产发布...'
            }
        }
    }

    // 流水线后置处理:不管成功失败都执行
    post {
        success {
            echo "✅ 流水线构建部署成功"
            // 可加钉钉/企业微信/邮件通知脚本
        }
        failure {
            echo "❌ 流水线执行失败,请查看日志排查"
        }
        always {
            echo "🔔 本次构建编号:${BUILD_NUMBER},构建地址:${BUILD_URL}"
            cleanWs()  // 每次跑完清空工作空间,防止磁盘爆满
        }
    }
}

2.3、pipeline实现部署jpress

注意:【scp 指定端口是大写的P】【ssh指定端口是小写的p】

《1》scp -P 22222 本地文件 root@192.168.1.30:/远程路径

《2》ssh -p 22222 root@192.168.1.30:/远程路径 ./本地路径

bash 复制代码
pipeline {
    agent any 
    // 定义全局变量,避免重复写
    environment {
        REMOTE_HOST = '192.168.1.30'
        REMOTE_USER = 'root'
        REMOTE_PORT = '22222'
        REMOTE_DIR = '/usr/local/jpsweb'
        WORKSPACE = '/data/jenkins/work2'
    }

    stages {
        stage('git clone code & build') {
            steps {
                ws(dir: "${WORKSPACE}") {
                    git(url: 'git@gitlab2.ck.com:ops/jpress.git', branch: 'master')
                    sh '''
                        export JAVA_HOME=/data/openjdk17
                        export PATH=$JAVA_HOME/bin:$PATH
                        /usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true
                    '''
                }
            }
        }

        stage('Copy to Remote Host') {
            steps {
                ws(dir: "${WORKSPACE}") {
                    script {
                        // 远程执行脚本
                        def shellScript = """
#!/bin/bash
ssh -p ${REMOTE_PORT} ${REMOTE_USER}@${REMOTE_HOST} 'rm -rf ${REMOTE_DIR} && mkdir -p ${REMOTE_DIR}'
scp -P ${REMOTE_PORT} starter/target/starter-4.0.zip ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/
scp -P ${REMOTE_PORT} start-jpress1.sh ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/
ssh -p ${REMOTE_PORT} ${REMOTE_USER}@${REMOTE_HOST} "cd ${REMOTE_DIR} && unzip -o starter-4.0.zip"
                        """
                        writeFile file: 'remote_deploy.sh', text: shellScript
                    }
                }
            }
        }

        stage('Execute Remote Script') {
            steps {
                ws(dir: "${WORKSPACE}") {
                    sh 'chmod +x remote_deploy.sh' 
                    sh './remote_deploy.sh'
                }
            }
        }

        stage('Start Service') {
            steps {
                script {
                    // 后台启动必须用 nohup,否则 Jenkins 断开连接服务会被杀掉
                    sh """
                        ssh -p ${REMOTE_PORT} ${REMOTE_USER}@${REMOTE_HOST} \\
                        "cd ${REMOTE_DIR} && chmod 755 start-jpress1.sh && nohup ./start-jpress1.sh > /dev/null 2>&1 &"
                    """
                }
            }
        }
    }
}
相关推荐
暗夜猎手-大魔王1 小时前
转载--一文彻底了解浏览器自动化,cdp、playwright、browser-user、midscene、browsermcp
人工智能·自动化
青主创享阁1 小时前
玄晶引擎XgenCore Works 2.9.2深度解析:自动化能力升级,重构私域与同城运营技术架构
重构·架构·自动化
idolao2 小时前
AutoTiny_5.0.0.1_win_x64自动化操作安装步骤详解(附AutoTiny自动化脚本与录制教程)
运维·自动化
橙色阳光五月天2 小时前
使用 hyperframes 结合其他技术是否可以做出XX动物园游览动态图
人工智能·ai·ai作画·自动化·视频
Flittly4 小时前
【日常小问】解决 Jenkins 部署 Spring Cloud 微服务到 Docker 容器启动失败的问题
运维·笔记·docker·微服务·jenkins
AC赳赳老秦4 小时前
故障自愈实战:用 OpenClaw 实现服务器日志自动化分析、根因定位、解决方案自动生成
大数据·运维·服务器·自动化·github·deepseek·openclaw
测试员周周4 小时前
【AI测试功能6】功能测试的自动化率:哪些该自动、哪些必须人工——AI测试人机协作决策指南
开发语言·人工智能·python·功能测试·单元测试·自动化·测试用例
霍格沃兹测试学院-小舟畅学5 小时前
Skill技术正在瓦解传统自动化框架的地位
运维·自动化
倔强的石头1066 小时前
云原生环境下的存储弹性与自动化:表空间目录动态挂载与冷热分层实践
运维·云原生·自动化