1.1 Jenkins+Docker+SpringCloud持续集成流程说明

docker中jenkins构建springBoot项目 jenkins docker springcloud_git

流程说明:

1)开发人员每天把代码提交到Gitlab代码仓库

2)Jenkins从Gitlab中拉取项目源码,编译并打成jar包,然后构建成Docker镜像,将镜像上传到Harbor私有仓库。

3)Jenkins发送SSH远程命令,让生产部署服务器到Harbor私有仓库拉取镜像到本地,然后创建容器。

4)最后,用户可以访问到容器

服务列表

docker中jenkins构建springBoot项目 jenkins docker springcloud_git_02

测试代码下载地址

wget https://cunqi0105-1300757323.cos.ap-shanghai.myqcloud.com/configuration-file/tensquareAdmin.zip
wget https://cunqi0105-1300757323.cos.ap-shanghai.myqcloud.com/configuration-file/tensquare_parent.zip

数据库文件下载

wget https://cunqi0105-1300757323.cos.ap-shanghai.myqcloud.com/configuration-file/mysql-sql.zip

项目架构:前后端分离

后端技术栈:SpringBoot+SpringCloud+SpringDataJpa(Spring全家桶)

微服务项目结构:

docker中jenkins构建springBoot项目 jenkins docker springcloud_docker_03


tensquare_parent:父工程,存放基础配置
tensquare_common:通用工程,存放工具类
tensquare_eureka_server:SpringCloud的Eureka注册中心
tensquare_zuul:SpringCloud的网关服务
tensquare_admin_service:基础权限认证中心,负责用户认证(使用JWT认证)
tensquare_gathering:一个简单的业务模块,活动微服务相关逻辑

数据库结构:

docker中jenkins构建springBoot项目 jenkins docker springcloud_docker_04


tensquare_user:用户认证数据库,存放用户账户数据。对应tensquare_admin_service微服务

tensquare_gathering:活动微服务数据库。对应tensquare_gathering微服务

微服务配置分析:

tensquare_eureka

tensquare_zuul

tensquare_admin_service

tensquare_gathering

1.3 环境准备(1)-Docker安装

详细请参考文档:Linux-Docker安装

1.4 环境准备(2)-Harbor镜像仓库安装及使用

详细请参考文档:企业级镜像仓库Harbor

1.5 微服务持续集成(1)-项目代码上传到Gitlab

在IDEA操作即可,参考之前的步骤。包括后台微服务和前端web网站代码

docker中jenkins构建springBoot项目 jenkins docker springcloud_jenkins_05

1.6 微服务持续集成(2)-从Gitlab拉取项目源码

1)Jenkins上创建 tenquare_back任务

docker中jenkins构建springBoot项目 jenkins docker springcloud_微服务_06


2) 创建参数化构建函数

docker中jenkins构建springBoot项目 jenkins docker springcloud_spring cloud_07


docker中jenkins构建springBoot项目 jenkins docker springcloud_docker_08


3)生成流水线脚本

docker中jenkins构建springBoot项目 jenkins docker springcloud_spring cloud_09


docker中jenkins构建springBoot项目 jenkins docker springcloud_spring cloud_10


4)创建Jenkinsfile文件

docker中jenkins构建springBoot项目 jenkins docker springcloud_docker_11

//gitlab的凭证
def git_auth = "14ae86e8-c3b4-4d7d-afe1-8c23d9fed317"
//gitlab的地址
def git_url = "git@192.168.5.4:root/tensquare_bak.git"

node {
    stage('拉取代码') {
        checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
    }
}

docker中jenkins构建springBoot项目 jenkins docker springcloud_git_12


6)项目测试

docker中jenkins构建springBoot项目 jenkins docker springcloud_docker_13

1.7 微服务持续集成(3)-提交到SonarQube代码审查

1) 创建参数化构建函数

docker中jenkins构建springBoot项目 jenkins docker springcloud_微服务_14


docker中jenkins构建springBoot项目 jenkins docker springcloud_微服务_15


2)在每个微服务项目的根目录下添加sonar-project.properties

docker中jenkins构建springBoot项目 jenkins docker springcloud_docker_16

# must be unique in a given SonarQube instance
sonar.projectKey=项目名称
# this is the name and version displayed in the SonarQube UI. Was mandatory
prior to SonarQube 6.1.
sonar.projectName=项目名称
sonar.projectVersion=1.0

# Path is relative to the sonar-project.properties file. Replace "\" by "/" on
Windows.
# This property is optional if sonar.modules is set.
sonar.sources=.
sonar.exclusions=**/test/**,**/target/**
sonar.java.binaries=.

sonar.java.source=1.8
sonar.java.target=1.8
# sonar.java.libraries=**/target/classes/**

# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8
3)修改Jenkinsfile构建脚本

//gitlab的凭证
def git_auth = "14ae86e8-c3b4-4d7d-afe1-8c23d9fed317"
//gitlab的地址
def git_url = "git@192.168.5.4:root/tensquare_bak.git"
// 构建版本的名称
def tag = "latest"

node {
    stage('拉取代码') {
        checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
    }
    stage('代码审查') {
        //定义当前Jenkins的SonarQubeScanner工具
        def scannerHome = tool 'sonarqube-scanner'
        //引用当前Jenkins SonarQube环境
        withSonarQubeEnv('sonarqube') {
            sh """
                cd ${project_name}
                ${scannerHome}/bin/sonar-scanner
            """
        }
    }
}

3)修改Jenkinsfile构建脚本

//gitlab的凭证
def git_auth = "14ae86e8-c3b4-4d7d-afe1-8c23d9fed317"
//gitlab的地址
def git_url = "git@192.168.5.4:root/tensquare_bak.git"
// 构建版本的名称
def tag = "latest"

node {
    stage('拉取代码') {
        checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
    }
    stage('代码审查') {
        //定义当前Jenkins的SonarQubeScanner工具
        def scannerHome = tool 'sonarqube-scanner'
        //引用当前Jenkins SonarQube环境
        withSonarQubeEnv('sonarqube') {
            sh """
                cd ${project_name}
                ${scannerHome}/bin/sonar-scanner
            """
        }
    }
}

docker中jenkins构建springBoot项目 jenkins docker springcloud_微服务_17


4)项目测试

docker中jenkins构建springBoot项目 jenkins docker springcloud_jenkins_18


docker中jenkins构建springBoot项目 jenkins docker springcloud_git_19

1.8 微服务持续集成(4)-使用Dockerfile编译、生成镜像

利用dockerfile-maven-plugin插件构建Docker镜像 1)在每个微服务项目的pom.xml加入dockerfile-maven-plugin插件(依赖父工程tensquare_common,不需要添加)

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>dockerfile-maven-plugin</artifactId>
    <version>1.3.6</version>
    <configuration>
        <repository>${project.artifactId}</repository>
        <buildArgs>
            <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
        </buildArgs>
    </configuration>
</plugin>

2)在每个微服务项目根目录下建立Dockerfile文件(依赖父工程tensquare_common,不需要添加)

#FROM java:8
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 10086
ENTRYPOINT ["java","-jar","/app.jar"]

3)修改Jenkinsfile构建脚本

//gitlab的凭证
def git_auth = "14ae86e8-c3b4-4d7d-afe1-8c23d9fed317"
//gitlab的地址
def git_url = "git@192.168.5.4:root/tensquare_bak.git"
// 构建版本的名称
def tag = "latest"

node {
   stage('拉取代码') {
       checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
   }
 stage('代码审查') {
  //定义当前Jenkins的SonarQubeScanner工具
  def scannerHome = tool 'sonarqube-scanner'
  //引用当前Jenkins SonarQube环境
  withSonarQubeEnv('sonarqube') {
   sh """
    cd ${project_name}
    ${scannerHome}/bin/sonar-scanner
   """
  }
 }
 stage('编译,构建镜像') {
  //定义镜像名称
  def imageName = "${project_name}:${tag}"

  //编译,安装公共工程
  sh "mvn -f tensquare_common clean install"

  //编译,构建本地镜像
  sh "mvn -f ${project_name} clean package dockerfile:build"
 }
}

4)项目测试

docker中jenkins构建springBoot项目 jenkins docker springcloud_微服务_20


docker中jenkins构建springBoot项目 jenkins docker springcloud_jenkins_21


5)编译失败

docker中jenkins构建springBoot项目 jenkins docker springcloud_docker_22


出现这种问题,是因为微服务具有相关的依赖,需要将tensquare_parent项目手动上传到maven本地仓库中

docker中jenkins构建springBoot项目 jenkins docker springcloud_spring cloud_23

1.9 微服务持续集成(5)-上传到Harbor镜像仓库

1)使用凭证管理Harbor私服账户和密码

docker中jenkins构建springBoot项目 jenkins docker springcloud_jenkins_24


2)生成凭证脚本代码

docker中jenkins构建springBoot项目 jenkins docker springcloud_docker_25


docker中jenkins构建springBoot项目 jenkins docker springcloud_spring cloud_26


3)修改Jenkinsfile构建脚本

//gitlab的凭证
def git_auth = "14ae86e8-c3b4-4d7d-afe1-8c23d9fed317"
//gitlab的地址
def git_url = "git@192.168.5.4:root/tensquare_bak.git"
// 构建版本的名称
def tag = "latest"
//Harbor私服地址
def harbor_url = "192.168.5.5:8080"
//Harbor的项目名称
def harbor_project_name = "tensquare"
//Harbor的凭证
def harbor_auth = "cd0b948d-e82b-4c0c-8a7c-8c6b8fb5454b"
node {
    stage('拉取代码') {
        checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
    }
    stage('代码审查') {
        //定义当前Jenkins的SonarQubeScanner工具
        def scannerHome = tool 'sonarqube-scanner'
        //引用当前Jenkins SonarQube环境
        withSonarQubeEnv('sonarqube') {
            sh """
                cd ${project_name}
                ${scannerHome}/bin/sonar-scanner
            """
        }
    }
    stage('编译,构建镜像') {
        //定义镜像名称
        def imageName = "${project_name}:${tag}"

        //编译,安装公共工程
        sh "mvn -f tensquare_common clean install"

        //编译,构建本地镜像
        sh "mvn -f ${project_name} clean package dockerfile:build"
        
        //给镜像打标签
        sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"
        //登录Harbor,并上传镜像
        withCredentials([usernamePassword(credentialsId: "${harbor_auth}",passwordVariable: 'password', usernameVariable: 'username')]) {

            //登录
            sh "docker login -u ${username} -p ${password} ${harbor_url}"
            //上传镜像
            sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
        }
        
        //删除本地镜像
        sh "docker rmi -f ${imageName}"
        sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"
    }
}

3)项目测试

docker中jenkins构建springBoot项目 jenkins docker springcloud_spring cloud_27


docker中jenkins构建springBoot项目 jenkins docker springcloud_git_28

4.10 微服务持续集成(6)-拉取镜像和发布应用

1)安装 Publish Over SSH 插件

Publish Over SSH

docker中jenkins构建springBoot项目 jenkins docker springcloud_jenkins_29


2)拷贝jenkins公钥到生产服务器

ssh-copy-id 192.168.5.6

3)添加远程服务器

docker中jenkins构建springBoot项目 jenkins docker springcloud_docker_30


docker中jenkins构建springBoot项目 jenkins docker springcloud_docker_31


4)添加一个port参数

docker中jenkins构建springBoot项目 jenkins docker springcloud_git_32


5)生成远程调用模板代码

docker中jenkins构建springBoot项目 jenkins docker springcloud_微服务_33


docker中jenkins构建springBoot项目 jenkins docker springcloud_spring cloud_34


6)修改Jenkinsfile构建脚本

//gitlab的凭证
def git_auth = "14ae86e8-c3b4-4d7d-afe1-8c23d9fed317"
//gitlab的地址
def git_url = "git@192.168.5.4:root/tensquare_bak.git"
// 构建版本的名称
def tag = "latest"
//Harbor私服地址
def harbor_url = "192.168.5.5:8080"
//Harbor的项目名称
def harbor_project_name = "tensquare"
//Harbor的凭证
def harbor_auth = "cd0b948d-e82b-4c0c-8a7c-8c6b8fb5454b"
node {
    stage('拉取代码') {
        checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
    }
	stage('代码审查') {
		//定义当前Jenkins的SonarQubeScanner工具
		def scannerHome = tool 'sonarqube-scanner'
		//引用当前Jenkins SonarQube环境
		withSonarQubeEnv('sonarqube') {
			sh """
				cd ${project_name}
				${scannerHome}/bin/sonar-scanner
			"""
		}
	}
	stage('编译,构建镜像') {
		//定义镜像名称
		def imageName = "${project_name}:${tag}"

		//编译,安装公共工程
		sh "mvn -f tensquare_common clean install"

		//编译,构建本地镜像
		sh "mvn -f ${project_name} clean package dockerfile:build"
		
		//给镜像打标签
		sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"
		//登录Harbor,并上传镜像
		withCredentials([usernamePassword(credentialsId: "${harbor_auth}",passwordVariable: 'password', usernameVariable: 'username')]) {

			//登录
			sh "docker login -u ${username} -p ${password} ${harbor_url}"
			//上传镜像
			sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
		}
		
		//删除本地镜像
		sh "docker rmi -f ${imageName}"
		sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"
		
		//=====以下为远程调用进行项目部署========
		sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh $harbor_url $harbor_project_name $project_name $tag $port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
	}
}

docker中jenkins构建springBoot项目 jenkins docker springcloud_git_35


2)配置NodeJS环境

docker中jenkins构建springBoot项目 jenkins docker springcloud_git_36


docker中jenkins构建springBoot项目 jenkins docker springcloud_docker_37


3)添加branch,project_name,port参数

docker中jenkins构建springBoot项目 jenkins docker springcloud_spring cloud_38


docker中jenkins构建springBoot项目 jenkins docker springcloud_微服务_39


docker中jenkins构建springBoot项目 jenkins docker springcloud_jenkins_40


4)编写dockerfile脚本

FROM nginx
COPY ./dist /usr/share/nginx/html
EXPOSE 80

5)编写Jenkinsfile构建脚本

//gitlab的凭证
def git_auth = "14ae86e8-c3b4-4d7d-afe1-8c23d9fed317"
//gitlab的地址
def git_url = "git@192.168.5.4:root/tensquare_front.git"
// 构建版本的名称
def tag = "latest"
//Harbor私服地址
def harbor_url = "192.168.5.5:8080"
//Harbor的项目名称
def harbor_project_name = "tensquare"
//Harbor的凭证
def harbor_auth = "cd0b948d-e82b-4c0c-8a7c-8c6b8fb5454b"
node {
    stage('拉取代码') {
        checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
    }
	stage('编译,构建镜像') {
		//定义镜像名称
		def imageName = "${project_name}:${tag}"
		//使用NodeJS 进行打包
     	nodejs('nodejs'){
         	 sh'''
          	  npm install
        	    npm run build
          	 '''
      }
    //生成镜像
    sh "docker build -t ${project_name}:${tag} ."
		//给镜像打标签
		sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"
		//登录Harbor,并上传镜像
		withCredentials([usernamePassword(credentialsId: "${harbor_auth}",passwordVariable: 'password', usernameVariable: 'username')]) {

			//登录
			sh "docker login -u ${username} -p ${password} ${harbor_url}"
			//上传镜像
			sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
		}

		//删除本地镜像
		sh "docker rmi -f ${imageName}"
		sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"

		//=====以下为远程调用进行项目部署========
		sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh $harbor_url $harbor_project_name $project_name $tag $port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
	}
}

6)编写deploy.sh部署脚本(之前编写过后,不用再次编写)

#! /bin/sh
#接收外部参数
harbor_url=$1
harbor_project_name=$2
project_name=$3
tag=$4
port=$5

imageName=docker中jenkins构建springBoot项目 jenkins docker springcloud_微服务_41harbor_project_name/docker中jenkins构建springBoot项目 jenkins docker springcloud_微服务_42tag

echo “$imageName”

#查询容器是否存在,存在则删除
containerId=docker ps -a | grep -w ${project_name}:${tag} | awk '{print $1}' if [ “$containerId” != “” ] ; then
#停掉容器
docker stop $containerId

#删除容器
docker rm $containerId

echo "成功删除容器"

fi

#查询镜像是否存在,存在则删除
imageId=docker images | grep -w $project_name | awk '{print $3}'

if [ “$imageId” != “” ] ; then

#删除镜像
docker rmi -f $imageId

echo "成功删除镜像"

fi

登录Harbor私服

docker login -u admin -p Harbor12345 $harbor_url

下载镜像

docker pull $imageName

启动容器

docker run -di -p docker中jenkins构建springBoot项目 jenkins docker springcloud_docker_43port $imageName

echo “容器启动成功”
7)修改代码连接后端微服务服务

docker中jenkins构建springBoot项目 jenkins docker springcloud_docker_44


docker中jenkins构建springBoot项目 jenkins docker springcloud_jenkins_45


8)项目测试

docker中jenkins构建springBoot项目 jenkins docker springcloud_docker_46


docker中jenkins构建springBoot项目 jenkins docker springcloud_微服务_47


docker中jenkins构建springBoot项目 jenkins docker springcloud_docker_48