开发者

jenkins如何通过pipeline部署springboot项目

开发者 https://www.devze.com 2024-09-25 10:43 出处:网络 作者: 海光之蓝
目录jenkins通过pipeline部署springboot项目部署方案总结jenkins通过pipeline部署springboot项目
目录
  • jenkins通过pipeline部署springboot项目
    • 部署方案
  • 总结

    jenkins通过pipeline部署springboot项目

    部署方案

    1、springboot项目不保存部署的pipeline或dockerfile构建脚本等与部署相关的问文件,业务项目只需关心业务,能够正常构建为jar包即可

    2、新建一个代码仓库,用于保存项目需要构建的Jenkinsfile

    3、jenkins配置pipeline地址,从仓库拉取要构建的项目进行构建和部署

    构建文件仓库示例结构如下:

    jenkins如何通过pipeline部署springboot项目

    4、jenkins配置

    jenkins如何通过pipeline部署springboot项目

    5、springboot项目镜像构建文件

    # 指定基础镜像,这是分阶段构建的前期阶段
    FROM eclipse-temurin:21-jre-alpine as builder
    
    # 设定时区、中文
    ENV TZ=Asia/Shanghai
    # 安装chrony包
    RUN apk add --no-cache chrony
    
    # 配置chrony
    RUN echo "server 0.pool.ntp.org iburst" >> /etc/chrony/chrony.conf
    RUN echo "server 1.pool.ntp.org iburst" >> /etc/chrony/chrony.conf
    RUN echo "server 2.pool.ntp.org iburst" >> /etc/chrony/chrony.conf
    RUN echo "server 3.pool.ntp.org iburst" >> /etc/chrony/chrony.conf
    
    # 执行工作目录
    WORKDIR application
    # 配置参数
    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
    # 启动chronyd服务
    CMD ["chronyd"]
    
    # 正式构建镜像
    FROM builder
    WORKDIR application
    # 前一阶段从jar中提取除了多个文件,这里分别执行COPY命令复制到镜像空间中,每次COPY都是一个layer
    COPY --from=builder application/dependencies/ ./
    COPY --from=builder application/spring-boot-loader/ ./
    COPY --from=builder application/snapshot-dependencies/ ./
    COPY --from=builder application/application/ ./
    # ENTRYPOINT  ["java", "org.springframework.boot.loader.JarLauncher"]
    # 分层构建传递参数写法
    ENTRYPOINT  ["sh","-c","java  $JAVA_OPTS org.springframework.boot.loader.JarLauncher $PARAMS"]
    
    # 新新
    # 例如: docker run -d -p 21991:2199 --name demo3 -e JAVA_OPTS="-Xmx128m"  -e PARAMS="--spring.application.name=test-demo" docker-demo:1.3
    #镜像放在最后,所传的java参数和覆盖配置文件参数写在docker镜像之前不然会导致传递失败
    

    基础镜像可选择:

    eclipse-temurin:21-jre-alpine
    eclipse-temurin:21-jdk-alpine
    openjdk:21
    openjdk:21-slim
    # 基于dibian构建
     bitnami/minideb
     Debian:bullseye-slim

    jenkins如何通过pipeline部署springboot项目

    6、demo项目docker-compose.yml文件

    services:
      demo:
        #  启动时传入镜像tag示例:BUILD_TAG=20240406-57 docker-compose up -d
        image: registry.cn-guangzhou.aliyuncs.com/lyr-test/demo:${BUILD_TAG}
        container_name: demo
        restart: always
        networkjs_mode: host
        deploy:
          resources:
            limits:
              cpus: '1.00'
              memory: 1G
            reservations:
              cpus: '0.10'
              memory: 256M
        environment:
          - JAVA_OPTS= -XX:+UseContainerSupport -XX:InitialRAMPercentage=75.0 -XX:MaxRAMPercentage=75.0 -XX:MinRAMPercentage=75.0
          # 当network_mode使用hots模式时,端口号设置不生效
          - PARAMS = --server.port=8080

    7、Jenkinsfile构建文件

    // 获取当前日期
    def current_date = new Date().format('yyyyMMdd')
    // 获取当前构建号
    def build_number = env.BUILD_NUMBER.toInteger()
    // 服务器集合
    def server_list = []
    // 所有的脚本命令放在pipeline中
    pipeline {
        // 指定任务在哪个集群节点中执行,any表示任意节点
        agent any
    
        parameters {
            string(description: '代码分支', name: 'CODE_BRANCH_PARAM', defaultValue: 'master', trim: true)
            // 这在Jenkins的凭据里设置的待部署服务器的名称就是服务器的ip;用docker-compose部署一般只会部署几台服务器,如果量大,建议上k8s
            booleanParam defaultValue: true, description: '10.0.24.8', name: 'SERVER_1'
            booleanParam description: '10.0.24.3', name: 'SERVER_2'
        }
    
        tools {
            git 'Default'
        }
    
        // 声明全局变量,方便后面修改使用
        environment {
            GIT_CONFIG_BRANCH = "master"
            GIT_CONFIG_ADDRESS = "https://*******/demo-jenkins.git"
            CODE_ADDRESS = "https://********/demo.git"
            // jenkins中创建的代码仓库密钥id
            CREDENTIALS_ID = 'git-credentials-id'
            IMG_REPO_CREDENTIALS_ID = 'img-repo-credentials-id'
            IMG_REPO = "registry.cn-guangzhou.aliyuncs.com"
            REPO_NAMESPACE = 'lyr-test'
            DEFAULT_BUILD_TAG = "${current_date}-${build_number}"
        }
    
        stages {
            stage('环境检测') {
                steps {
                    // 构建环境检测
                    sh '''
                         cat /proc/version
                         free -m
                         df -h
                         docker -v
                         git -v
                         mvn -v
                         java -version
                       '''
                    echo '环境检测完成'
                }
            }
            stage('拉取配置文件') {
                steps {
                    echo "拉取配置文件代码分支:${GIT_CONFIG_BRANCH}"
                    sh "pwd"
                    dir('/var/jenkins编程客栈_home/workspace/pipeline/') {
                        sh "pwd"
                        echo "${CREDENTIALS_ID}"
                        checkout scmGit(branches: [[name: "${GIT_CONFIG_BRANCH}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${CREDENTIALSphp_ID}", url: "${GIT_CONFIG_ADDRESS}"]])
                    }
                    sh "pwd"
                }
            }
            stage('拉取代码') {
                steps {
                    echo pwd
                    // BRANCH为构建分支参数
                    git branch: "${CODE_BRANCH_PARAM}", credentialsId: "${CREDENTIALS_ID}", url: "${CODE_ADDRESS}"
                }
            }
            stage('maven构建') {
                steps {
                    echo pwd
                    sh """
                      mvn clean package -U -Dmaven.test.skip=true
                    """
                }
            }
            stage('生成镜像') {
                steps {
                    echo pwd
                    // JOB_NAME为项目名变量(内置的环境变量) TAG为设置的变量标签
                    sh '''
                     cp /var/jenkins_home/workspace/pipeline/${JOB_NAME}/Dockerfile /var/jenkins_home/workspace/${JOB_NAME}
                    '''
                    script {
                        echo "当前镜像tag:${DEFAULT_BUILD_TAG}"
                        sh "docker build -f Dockerfile  -t ${IMG_REPO}/${REPO_NAMESPACE}/${JOB_NAME}:${DEFAULT_BUILD_TAG} ."
                    }
                }
            }
            stage('推送镜像') {
                steps {
                    withCredentials([usernamePassword(credentialsId: 'img-repo-credentials-id', passwordVariable: 'IMG_PWD', usernameVariable: 'IMG_USER')]) {
                        sh '''
                   	       echo "${IMG_PWD}" | docker login --username ${IMG_USER} --password-stdin ${IMG_REPO}
                           docker image prune -f
                           docker push ${IMG_REPO}/${REPO_NAMESPACE}/${JOB_NAME}:${DEFAULT_BUILD_TAG}
                        '''
                    }
                }
    
            }
            stage('清理') {
                steps {
                    sh '''
                   	# 退出镜像仓库
                   # docker logout ${IMG_REPO}
                    # 清理前镜像
                   # docker images
                    # 删除指定镜像
                   # docker rmi ${IMG_REPO}/${REPO_NAMESPACE}/${JOB_NAME}:${PRE_BUILD_TAG}
                    # 命令删除,删除最早一个
                   # docker images | grep "demo" | sort -r | tail -n 1 | awk '{print $3}'  | xargs docker rmi
                    # 清理后镜像
                    docker images
                    '''
                }
            }
            stage('部署至服务器') {
                steps {
                    script {
                        script {
                            echo "SERVER_1:" + SERVER_1
                            if (SERVER_1=="true") {
                                server_list.add('10.0.24.8')
                            }
                            echo "SERVER_2:" + SERVER_2
                            if (SERVER_2=="true") {
                                server_list.add('10.0.24.3')
                            }
                            for (server_ip in server_list) {
                                echo "当前部署的服务器id:${server_ip}"
                                withCredentials([usernamePassword(credentialsId: server_ip, passwordVariable: 'SERVER_PWD', usernameVariable: 'SERVER_USER')]) {
                                    node {
                                        def remote = [:]
                                        remote.name = "deploy"
                                        remote.host = server_ip
                                        remote.user = "${SERVER_USER}"
                                        remote.password = "${SERVER_PWD}"
                                        remote.allowAnyHosts = true
                                        stage('远程ssh部署') {
                                            echo "当前远程ssh部署的项目名:${JOB_NAME}"
                                            sshCommand remote: remote, command: "mkdir -p /data/${JOB_NAME}"
                                            sshPut remote: remote, from: """/var/jenkins_home/workspace/pipeline/${JOB_NAME}/docker-compose.yaml""", into: """/data/${JOB_NAME}"""
                                            sshCommand remote: remote, command: """
                                                cd /data/${JOB_NAME}/
                                                BUILD_TAG=${DEFAULT_BUILD_TAG} docker-compose up -d
                                                docker-compose ps
                                            """
                                            echo "ssh部署脚本执行完成"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    
        // 通知内容
        post {
            success {
                //成功通知
                echo "成功通知"
    
            }
            failure {
                // 失败通知
                echo "失败通知"
            }
        }
    }

    8、jenkins中配置Jenkinsfile中使用到的代码仓库凭据,镜像仓库凭据和服务器密码凭据

    jenkins如何通过pipeline部署springboot项目

    9、配置完成后,点击构建就行

    jenkins如何通过pipeline部署springboot项目

    10、当首次部署到新服务器时,需要登录镜像仓库,可以手动登录,也可以在jenkins中进行配置,每次发布都要登录,不然会拉取镜像错误

    // 服务器集合
    def server_list = []
    // 所有的脚本命令放在pipeline中
    pipeline {
        // 指定任务在哪个集群节点中执行,any表示任意节点
        agent any
    
        parameters {
            choice(description: '服务名', name: 'SERVICE_NAME', choices: ["demo"])
            string(description: '镜像tag', name: 'BUILD_TAG_PARAM', defaultValue: '20240405-01', trim: true)
            booleanParam defaultValue: true, description: '10.0.24.8', name: 'SERVER_1'
            booleanParam description: '10.0.24.3', name: 'SERVER_2'
        }
    
        tools {
            git 'Default'
        }
    
        // 声明全局变量,方便后面修改使用
        environment {
            GIT_CONFIG_BRANCH = "master"
            GIT_CONFIG_ADDRESS = "https://******/demo-jenkins.git"
            // jenkins中创建的代码仓库密钥id
            CREDENTIALS_ID = 'git-credentials-id'
            IMG_REPO_CREDENTIALS_ID = 'img-repo-credentials-id'
            IMG_REPO = "registry.cn-guangzhou.aliyuncs.com"
            REPO_NAMESPACE = 'lyr-test'
        }
    
        stages {
          android  stage('环境检测') {
                steps {
                    // 构建环境检测
                    sh '''
                         cat /proc/version
                         free -m
                         df -h
                         docker -v
                         git -v
                         mvn -v
                         java -version
                       '''
                    echo '环境检测完成'
                }
            }
            stage('拉取配置文件') {
                steps {
                    echo "拉取配置文件代码分支:${GIT_CONFIG_BRANCH}"
                    sh "pwd"
                    dir('/var/jenkins_home/workspace/pipeline/') {
                        sh "pwd"
                        echo "${CREDENTIALS_ID}"
                        checkout scmGit(branches: [[name: "${GIT_CONFIG_BRANCH}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${CREDENTIALS_ID}", url: "${GIT_CONFIG_ADDRESS}"]])
                    }
                    sh "pwd"
                }
            }
            stage('登录镜像') {
                steps {
                    withCredentials([usernamePassword(credentialsId: 'img-repo-credentials-id', passwordVariable: 'IMG_PWD', usernameVariable: 'IMG_USER')]) {
                        script {
                            echo "SERVER_1:" + SERVER_1
                            if (SERVER_1=="true") {
                                server_list.add('10.0.24.8')
                            }
                            echo "SERVER_2:" + SERVER_2
                            if (SERVER_2=="true") {
                                server_list.add('10.0.24.3')
                            }
                            for (server_ip in server_list) {
                                echo "当前部署的服务器id:${server_ip}"
                                withCredentials([usernamePassword(credentialsId: server_ip, passwordVariable: 'SERVER_PWD', usernameVariable: 'SERVER_USER')]) {
                                    node {
                                        def remote = [:]
                                        remote.name = "deploy"
                                        remote.host = server_ip
                                        remote.user = "${SERVER_USER}"
                                        remote.password = "${SERVER_PWD}"
                                        remote.allowAnyHosts = true
                                        stage('远程ssh部署') {
                                            echo "当前远程ssh登录的服务器ip:${server_ip}"
                                            sshCommand remote: remote, command: """
                                                echo "${IMG_PWD}" | docker login --username ${IMG_USER} --password-stdin ${IMG_REPO}
                                            """
                                            echo "镜像ssh部署脚本执行完成"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            stage('部署至服务器') {
                steps {
                    script {
                        script {
                            echo "SERVER_1:" + SERVER_1
                            if (SERVER_1=="true") {
                                server_list.add('10.0.24.8')
                            }
                            echo "SERVER_2:" + SERVER_2
                            if (SERVER_2=="true") {
                                server_list.add('10.0.24.3')
                            }
                            for (server_ip in server_list) {
                                echo "当前部署的服务器id:${server_ip}"
                                withCredentials([usernamePassword(credentialsId: server_ip, passwordVariable: 'SERVER_PWD', usernameVariable: 'SERVER_USER')]) {
                                    node {
                                        def remote = [:]
                                        remote.name = "deploy"
                                        remote.host = server_ip
                                        remote.user = "${SERVER_USER}"
                                        remote.password = "${SERVER_PWD}"
                                        remote.allowAnyHosts = true
                                        stage('远程ssh部署') {
                                            echo "当前远程ssh部署的项目名:${SERVICE_NAME}"
                                            sshCommand remote: remote, command: "mkdir -p /data/${SERVICE_NAME}"
                                            sshPut remote: remote, from: """/var/jenkins_home/workspace/pipeline/${SERVICE_NAME}/docker-compose.yaml""", into: """/data/${SERVICE_NAME}"""
                                            sshCommand remote: remote, command: """
                                                cd /data/${SERVICE_NAME}/
                                                BUILD_TAG=${BUILD_TAG_PARAM} docker-compose up -d
                                                docker-compose ps
                                            """
                                     编程客栈       echo "ssh部署脚本执行完成"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    
        // 通知内容
        post {
            success {
                //成功通知
                echo "成功通知"
    
            }
            failure {
                // 失败通知
                echo "失败通知"
            }
        }
    }

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号