Jenkins流水线案例

wen java案例 2

本文目录导读:

Jenkins流水线案例

  1. 案例背景设定
  2. 案例一:声明式流水线(推荐)
  3. 案例二:脚本式流水线(更灵活)
  4. 流水线中常见问题的处理技巧
  5. 如何在 Jenkins 中使用?
  6. 你需要准备的环境清单

下面我将为你提供一个比较完整的 Jenkins 流水线案例,这个案例涵盖了开发环境部署自动化测试构建镜像推送镜像以及生产环境发布的全流程。

我会提供两种主要类型的案例,你可以根据你的实际需求选择参考:

  1. 声明式流水线(Declarative Pipeline)——官方推荐,结构清晰,易于维护。
  2. 脚本式流水线(Scripted Pipeline)——更灵活,基于 Groovy 编程。

案例背景设定

  • 项目:一个简单的 Java Spring Boot 应用(假设代码存放在 GitLab 或 GitHub)。
  • 技术栈:Maven + JDK 11 + Docker + Kubernetes(可选)。
  • 环境:测试环境(Test)、生产环境(Prod)。
  • 目标:代码提交后,自动编译、测试、构建镜像,推送到镜像仓库,然后部署到测试环境;当手动点击“发布”时,部署到生产环境。

声明式流水线(推荐)

这是最常用的方式,使用 pipeline 块定义整个流程。

// Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any  // 或者指定 label: 'docker-agent',表示使用带有 Docker 的构建机
    // 全局环境变量
    environment {
        // 镜像仓库地址(需提前在 Jenkins 全局配置中配置凭证)
        REGISTRY = 'registry.cn-hangzhou.aliyuncs.com'
        // 项目命名空间
        NAMESPACE = 'my-project'
        // 应用名称(与代码仓库名保持一致)
        APP_NAME = 'spring-boot-demo'
        // 镜像完整标签(使用构建号作为版本)
        IMAGE_TAG = "${BUILD_NUMBER}"
        // 完整镜像名称
        IMAGE_FULL_NAME = "${REGISTRY}/${NAMESPACE}/${APP_NAME}:${IMAGE_TAG}"
        // 引入 Jenkins 中配置的 Docker Hub / 阿里云镜像仓库的凭证 ID(ID 需在 Jenkins 中创建)
        DOCKER_CREDENTIALS = credentials('docker-registry-credentials')
    }
    // 参数化构建(允许手动触发时选择部署环境)
    parameters {
        choice(name: 'DEPLOY_ENV', choices: ['test', 'prod'], description: '选择要部署的环境')
        string(name: 'BRANCH', defaultValue: 'master', description: '要构建的分支')
    }
    stages {
        stage('① 拉取代码') {
            steps {
                echo "正在拉取分支: ${params.BRANCH}"
                // 使用 Git 插件拉取(需在 Jenkins 中配置好 Git 凭证)
                checkout scmGit(
                    branches: [[name: "${params.BRANCH}"]],
                    userRemoteConfigs: [[url: 'https://gitlab.com/my-project/spring-boot-demo.git', 
                                        credentialsId: 'gitlab-credentials']]
                )
            }
        }
        stage('② 编译 & 单元测试') {
            steps {
                // 使用 Maven 容器进行构建(避免在宿主机安装依赖)
                script {
                    // 这里如果使用 agent any,需要宿主机有 mvn;更推荐使用 docker 容器
                    // sh 'mvn clean package -DskipTests=false'
                    // 使用 Docker 运行 Maven 构建(假设构建机有 Docker)
                    sh '''
                        docker run --rm -v "$WORKSPACE":/app -w /app \
                        maven:3.8.6-jdk-11 \
                        mvn clean package -Dmaven.test.skip=false
                    '''
                }
            }
            post {
                success {
                    echo "编译测试成功 ✅"
                    // 归档产物(Jar 包)方便 Jenkins 页面下载
                    archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
                }
                failure {
                    echo "编译测试失败 ❌"
                    // 可以发送邮件通知
                }
            }
        }
        stage('③ 构建 Docker 镜像') {
            steps {
                script {
                    // 假设项目根目录有 Dockerfile
                    sh '''
                        docker build -t ${IMAGE_FULL_NAME} .
                    '''
                }
            }
        }
        stage('④ 推送镜像到仓库') {
            steps {
                script {
                    sh '''
                        echo "${DOCKER_CREDENTIALS_PSW}" | docker login ${REGISTRY} -u ${DOCKER_CREDENTIALS_USR} --password-stdin
                        docker push ${IMAGE_FULL_NAME}
                    '''
                }
            }
            post {
                success {
                    echo "镜像推送成功 🎉"
                    // 清理本地镜像,避免磁盘占用
                    sh 'docker rmi ${IMAGE_FULL_NAME}'
                }
            }
        }
        stage('⑤ 部署应用') {
            // 根据参数决定执行哪个环境的部署脚本
            when {
                expression { params.DEPLOY_ENV == 'test' }
            }
            steps {
                echo "部署到测试环境..."
                // 方式一:通过 SSH 远程执行命令(需要 SSH Agent 插件)
                sshagent(['test-server-ssh']) {
                    sh '''
                        ssh -o StrictHostKeyChecking=no root@test-server-ip \
                        "cd /opt && docker-compose pull app && docker-compose up -d app"
                    '''
                }
                // 方式二:如果是 Kubernetes,可以使用 kubectl 命令
                // sh "kubectl set image deployment/${APP_NAME} ${APP_NAME}=${IMAGE_FULL_NAME} --record"
            }
        }
        stage('⑥ 生产环境发布(手动批准)') {
            // 只有选择了 prod 环境才会执行,且需人工确认
            when {
                expression { params.DEPLOY_ENV == 'prod' }
            }
            input {
                message "确定将 [${APP_NAME}:${IMAGE_TAG}] 发布到生产环境?"
                ok "确认发布"
                parameters {
                    string(name: 'REASON', defaultValue: '', description: '请输入发布说明')
                }
            }
            steps {
                echo "发布原因: ${REASON}"
                script {
                    // 生产环境发布脚本(严谨场景会有金丝雀发布或滚动发布)
                    sshagent(['prod-server-ssh']) {
                        sh '''
                            ssh root@prod-server-ip \
                            "docker pull ${IMAGE_FULL_NAME} && docker stop ${APP_NAME} || true && docker rm ${APP_NAME} || true && \
                             docker run -d --name ${APP_NAME} -p 8080:8080 ${IMAGE_FULL_NAME}"
                        '''
                    }
                }
            }
            post {
                success {
                    echo "✅ 生产环境发布成功!"
                    // 发送企业微信/钉钉通知
                }
            }
        }
    }
    // 构建结果处理(无论成功失败都执行)
    post {
        always {
            echo "流水线执行完毕,构建结果: ${currentBuild.currentResult}"
            cleanWs() // 清理工作区
        }
        failure {
            // 可以在这里配置邮件通知
            emailext subject: "构建失败: ${APP_NAME}",
                      body: "请查看 Jenkins 构建日志。",
                      to: "team@example.com"
        }
    }
}

脚本式流水线(更灵活)

这种方式用 nodestage 方法实现,更贴近 Groovy 编程,适合复杂逻辑。

// Jenkinsfile (Scripted Pipeline)
// 定义仓库地址
def registry = "registry.cn-hangzhou.aliyuncs.com"
def appName = "spring-boot-demo"
def repoUrl = "https://gitlab.com/my-group/spring-boot-demo.git"
def credentialsId = "gitlab-credentials"
node('docker') { // 指定使用带有 docker 标签的 agent
    // 定义整个流程
    stage('Checkout') {
        checkout scmGit(
            branches: [[name: 'main']],
            userRemoteConfigs: [[url: repoUrl, credentialsId: credentialsId]]
        )
    }
    def version = "${BUILD_NUMBER}"
    def imageFullName = "${registry}/my-project/${appName}:${version}"
    def containerName = "spring-boot-app"
    stage('Test & Build') {
        try {
            // 在 Docker 容器中运行 Maven
            sh "docker run --rm -v ${WORKSPACE}:/app -w /app maven:3.8.6-jdk-11 mvn clean package -DskipTests=false"
        } catch (Exception e) {
            currentBuild.result = 'FAILURE'
            throw e
        }
    }
    stage('Build Image') {
        sh "docker build -t ${imageFullName} ."
    }
    stage('Push Image') {
        withCredentials([usernamePassword(credentialsId: 'docker-registry', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASS')]) {
            sh """
                docker login ${registry} -u ${DOCKER_USER} -p ${DOCKER_PASS}
                docker push ${imageFullName}
            """
        }
    }
    // 默认部署到测试环境
    def deployEnv = params.DEPLOY_ENV ?: 'test'
    if (deployEnv == 'prod') {
        stage('Deploy to Prod') {
            timeout(time: 1, unit: 'HOURS') {
                input message: "确认部署 ${imageFullName} 到生产环境?", ok: '部署'
            }
            sh """
                ssh root@prod-server "docker pull ${imageFullName} && docker rm -f ${containerName} || true && docker run -d -p 8080:8080 --name ${containerName} ${imageFullName}"
            """
        }
    } else {
        stage('Deploy to Test') {
            sh """
                ssh root@test-server "docker pull ${imageFullName} && docker-compose up -d"
            """
        }
    }
    stage('Cleanup') {
        // 清理 Docker 镜像
        sh "docker rmi ${imageFullName} || true"
        deleteDir() // 清理工作空间
    }
}

流水线中常见问题的处理技巧

  1. agent anyagent docker: 建议在 Jenkins 中配置一个带有 Docker 和 JDK 的构建节点,然后使用 agent { docker { image 'maven:3.8.6-jdk-11' } },这样可以保证构建环境的干净和统一。

  2. 关于凭证管理: 不要明文将账号密码写在 Jenkinsfile 中,使用 Jenkins 的 Credentials(凭证) 功能,然后在流水线中用 credentials()withCredentials() 引入。

  3. 构建失败”的处理: 如果不希望整个流程停止(比如测试覆盖率过低仅告警),可以使用 catchError(buildResult: 'SUCCESS', stageResult: 'UNSTABLE') 包裹。

  4. 使用 Blue Ocean 插件: 强烈建议安装 Blue Ocean 插件,它能让流水线的可视化界面更漂亮,排错更方便。


如何在 Jenkins 中使用?

  1. 新建任务:创建一个“流水线”类型(Pipeline)的任务。
  2. 配置流水线
    • 方式 A(推荐):在“流水线 -> 定义”中选择 “Pipeline script from SCM”,然后指向你的代码仓库(这样 Jenkinsfile 就跟着代码走了,更规范)。
    • 方式 B:选择 “Pipeline script”,将上述代码复制粘贴进去。
  3. 执行:点击“立即构建”,如果使用了参数化构建,Jenkins 会弹出选项让你选择分支和环境。

你需要准备的环境清单

  • [ ] Git 仓库(存放代码和 Jenkinsfile)
  • [ ] Jenkins 环境(安装 Git、Docker、Pipeline 等插件)
  • [ ] Docker Hub / 阿里云容器镜像服务(用于存放镜像)
  • [ ] 目标服务器(测试/生产环境,需要有 Docker 环境)

如果你有具体的场景,比如使用 Kubernetes 部署、或者涉及前后端分离、微服务多模块部署,可以告诉我,我可以提供更贴合你需求的案例。

抱歉,评论功能暂时关闭!