Jenkins流水线 CI/CD 基于 Jenkinsfile 的 SpringBoot2 web 项目 (Git+[DooD]Docker+Maven+Harbor)
blank
blank
发布于 2019-07-31 / 1005 阅读 / 0 评论 / 0 点赞

Jenkins流水线 CI/CD 基于 Jenkinsfile 的 SpringBoot2 web 项目 (Git+[DooD]Docker+Maven+Harbor)

前言

最近才发现,现在一直在用的 Jenkins 项目,都是使用的已经不被推荐的 Maven 项目方式来跑的,如图

jenkins-maven-old

缺点很明显
  • 首先,每一个分支都得新建一个新的除了版本号不同的完全重复的Maven项目来跑.版本多了之后看起来非常杂乱.
  • 其次, 每次有新的项目开发时,都必须自己手动创建一个 Systemd 系统服务,服务里面挂一个启动脚本,启动脚本来运行 打包好的 jar 包,如图 jenkins-maven-old-bash
  • 项目的备份工作,都得自己在 Jenkins 的 Maven 项目中自己写各种备份清理脚本来完成.

这两天有空学习了下新的基于 Jenkinsfile 的 Pipline 流水线项目,相比之前确实更加方便.

安装 Docker 安装方法请参见 centos7 yum 安装 docker-ce & docker-compose

运行 Jenkins

docker run -u root -p 8080:8080 -p 50000:50000 --name jenkins \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /docker/jenkins/jenkins_home:/var/jenkins_home \
-v /etc/timezone:/etc/timezone \
-v /etc/localtime:/etc/localtime \
-v ~/.ssh:/var/jenkins_home/.ssh \
-v /usr/lib/x86_64-linux-gnu/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7 \
-v ~/.m2:/root/.m2 \
-d jenkinsci/blueocean
参数说明
  • -u root 以root 用户运行,解决部分权限不足导致的意外问题,以及正确设置默认的 Maven 配置文件,以使用阿里镜像加速 Maven 编译时下载依赖Jar包的速度.
  • -p 8080:8080 -p 50000:50000 映射 8080 和 50000 端口
  • --name jenkins 自定义 docker 镜像名称为 jenins
  • --restart=always 出错自动重启
  • -v /var/run/docker.sock:/var/run/docker.sock 映射宿主机的 Docker 我们这里不在本身就在 Docker 中运行的 Jenkins 安装 Docker [Docker inside Docker (DinD)] 否则,将会产生更多的垃圾,也不便于维护 我们使用官方推荐的 Docker outside of Docker (DooD) 模式,直接调用宿主机中的 Docker 即可
  • -v /etc/timezone:/etc/timezone -v /etc/localtime:/etc/localtime 解决时区 默认为UTC 而不是CST问题
  • -v ~/.ssh:/var/jenkins_home/.ssh 共享宿主机的 ssh密钥,方便连接宿主机已经连接过的其他主机
  • -v /usr/lib/x86_64-linux-gnu/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7 运行依赖
  • -v ~/.m2:/root/.m2 共享宿主机的 Maven 仓库及 Maven 配置文件
  • -d 后台运行模式
  • jenkinsci/blueocean Jenkins 集成 blueocean 的 Docker 镜像 不加:tag = :latest 表示默认使用最新版本
  • ps 如果是第一次运行这个 docker docker 将会在 执行 run 操作前 自动执行 pull 操作, 所以 pull 操作完全可以省略:D

执行完成后 访问 宿主机ip:8080(这里可以配置 nginx 到 8080 端口的跳转 配置完成后访问你nginx 自定义的域名/后缀即可) jenkins-0 过一会儿会自动启动完成
启动完成后会要求输入临时随机密码 jenkins-1 2 种方法查询密码 选其中一种即可

1 docker logs -f jenkins 日志中会有
2 docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword

输入完密码进入自定义 Jenkins jenkins-2 我们这里选择 安装推荐的插件即可 点击后会自动安装推荐的插件 jenkins-3 安装完成后会自动进入 创建第一个管理员用户界面 输入完成点击保存并完成(这一步中创建的账号就是管理员权限的账号) jenkins-4 进入 实例配置界面
这里需要注意 如果你前面有配置nginx 对应的域名跳转的话 在这里就需要填入之前的配置值
如果 你之前 配置了 https://jenkins.xx.com 这里就填入一样的就好 如果没有 保持默认的 ip 地址 即可.
点击保存并完成 jenkins-5 就绪 jenkins-6 下面安装 Pipeline Utility Steps 插件 流水线中的readMavenPom需要 jenkins-system-management-plugins-install 这里因为我已经安装完成所以这个插件会显示在已安装列表中 jenkins-system-management-plugins-installed

配置 harbor 账号凭据 jenkins-pipline-harbor-account-setup jenkins-pipline-harbor-account-setup-2 jenkins-pipline-harbor-account-setup-3 在这里输入你配置的 harbor 账号密码 jenkins-pipline-harbor-account-setup-4 配置完成 harbor 账号后
打开 BlueOcean jenkins-pipline-blueocean-open 点击创建新的流水线 jenkins-pipline-blueocean-create-pipline-0 选择代码仓库 git jenkins-pipline-blueocean-create-pipline-1 输入项目的git地址 输入对应的 git 账号密码 点击创建证书 jenkins-pipline-blueocean-create-pipline-2 点击创建流水线 jenkins-pipline-blueocean-create-pipline-3 流水线创建完成会自动执行所有分支的流水线(前提是项目根目录存在Jenkinsfile文件) jenkins-pipline-blueocean-create-pipline-6 切换到分支视图 点击运行按钮即可执行对应分支的流水线 jenkins-pipline-blueocean-create-pipline-5 流水线执行效果如下 jenkins-pipline-blueocean-create-pipline-7 执行完成后我们也可以去harbor上检查镜像是否已经上传成功 jenkins-pipline-blueocean-harbor-docker-list springboot 项目非常简单 使用idea直接创建一个springboot的项目 maven.pom文件如下 jenkins-pipline-blueocean-idea-maven 自定义server.port改为9001 jenkins-pipline-blueocean-idea-application.properties 新建一个webController 用来测试项目是否运行正常 jenkins-pipline-blueocean-idea-web-controller 执行完成后 访问主机:9001 jenkins-pipline-blueocean-create-pipline-9 拉新分支后记得修改pom.xml中的VERION
比如 master分支 中 version 为 latest
1.0分支 中 version 为 1.0
打包后的 docker镜像 tag 既是以此作为区分 当然你也可以自行修改定义 jenkins-pipline-blueocean-create-pipline-10 我的Jenkinsfile

#!/usr/bin/env groovy
pipeline {

    agent any
    // using the Timestamps plugin we can add timestamps to the console log
    options {
        timestamps()
    }

    environment {

        GROUPID = readMavenPom().getGroupId()//com.blankhang
        ARTIFACTID = readMavenPom().getArtifactId()//jenkins
        VERSION = readMavenPom().getVersion()//1.0

        HARBOR_HOST = "registry.xx.com"//请修改为自己的harbor域名/ip
        BUILD_PREFIX = "blank"
        HARBOR_IMG_NAME = "${HARBOR_HOST}/${BUILD_PREFIX}/${ARTIFACTID}:${VERSION}"
        SERVER_PORT = 9001
    }

    stages {
        stage('停止服务') {
            steps {
                echo '清理旧版本容器'
                sh 'docker ps -f name=${ARTIFACTID} -q | xargs --no-run-if-empty docker container stop'
                sh 'docker container ls -a -fname=${ARTIFACTID} -q | xargs -r docker container rm'
            }
        }

//        stage('代码测试') {
//        agent {
//            docker {
//                image 'maven:3-alpine'
//                //让docker 使用 host 宿主机的 m2仓库 使用root用户来运行 以让指定的~/.m2/config/setting.xml 阿里加速下载maven 依赖生效
//                args '-v $HOME/.m2:/root/.m2:z -u root'
//                reuseNode true
//            }
//        }
//            steps{
//                echo "代码测试"
//                sh "mvn test"
//            }
//        }

        stage('Maven构建') {
            agent {
                docker {
                    image 'maven:3-alpine'
                    //让docker 使用 host 宿主机的 m2仓库 使用root用户来运行 以让指定的~/.m2/config/setting.xml 阿里加速下载maven 依赖生效
                    args '-v $HOME/.m2:/root/.m2:z -u root'
                    reuseNode true
                }
            }
            steps {
                echo "代码编译"
                sh "mvn clean package  -Dmaven.test.skip=true"
            }
        }

        // 项目打包到镜像并推送到镜像仓库
        stage('构建Docker镜像') {
            steps {
                echo "项目打包成镜像并推送到harbor镜像私服"
                    sh '''
                echo '
                FROM openjdk:8-jdk-alpine
                COPY target/*.jar app.jar
                ENV TZ Asia/Shanghai
                EXPOSE 9001
                ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
                ' > Dockerfile
                docker build -t ${HARBOR_IMG_NAME} .
                       '''
            }
        }

        stage('推送镜像到Harbor') {
            steps{

			//请注意这里的'harbor'即是之前在Jenkins凭据中所填写的凭据id
                        withCredentials([usernamePassword(credentialsId: 'harbor', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
                        //登陆到harbor
                        sh "docker login ${HARBOR_HOST} -u $USERNAME -p $PASSWORD"
                        //推送镜像到harbor私服
                        sh "docker push ${HARBOR_IMG_NAME}"
                }
            }
        }

        stage('启动服务') {
            steps {
                echo "start ${ARTIFACTID}"
                // 部署服务
                sh 'docker run -d --restart=always -p ${SERVER_PORT}:${SERVER_PORT} --name ${ARTIFACTID} ${HARBOR_IMG_NAME}'
            }
        }
    }
}

评论