Jenkins+Docker+Harbor+SpringCloud微服务持续集成自动化部署(上)

简介: Jenkins+Docker+Harbor+SpringCloud微服务持续集成自动化部署(上)

正文


1 Jenkins+Docker+SpringCloud微服务持续集成(上)


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


55555.png

大致流程说明:


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


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


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


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


服务列表


名称 IP地址

安装软件

持续基础服务器

192.168.5.3

jenkins,JDK,Maven,Git,SonarQube,Docker,MySQL

代码托管服务器 192.168.5.4 gitlab-ce
Docker仓库服务器 192.168.5.5 Docker,Harbor
生产部署服务器 192.168.5.6 Docker


1.2 SpringCloud微服务源码概述


# 测试代码下载地址
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全家桶)


微服务项目结构:


000000.png


tensquare_parent:父工程,存放基础配置


tensquare_common:通用工程,存放工具类


tensquare_eureka_server:SpringCloud的Eureka注册中心


tensquare_zuul:SpringCloud的网关服务


tensquare_admin_service:基础权限认证中心,负责用户认证(使用JWT认证)


tensquare_gathering:一个简单的业务模块,活动微服务相关逻辑


数据库结构:


image-20210522203821293.png


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网站代码


888.png


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


1)Jenkins上创建 tenquare_back任务


8888.png


2) 创建参数化构建函数


88.png

80.png


3)生成流水线脚本


800.png

08.png


4)创建Jenkinsfile文件


008.png


//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}"]]])
    }
}


5)上传代码


080.png


6)项目测试


0800.png


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


1) 创建参数化构建函数


11.png

111.png


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


1112.png


# 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
            """
        }
    }
}

22.png


4)项目测试


223.png

224.png


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)项目测试


33.png

44.png


5)编译失败


55.png


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


234.png


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


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


56.png


2)生成凭证脚本代码


57.png

58.png


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)项目测试


89.png

778.png


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


1)安装 Publish Over SSH 插件

212.png



Publish Over SSH


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


ssh-copy-id 192.168.5.6


3)添加远程服务器


213.png

214.png


4)添加一个port参数


215.png


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


216.png


217.png


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)])
  }
}

218.png


2)配置NodeJS环境


219.png

220.png


3)添加branch,project_name,port参数


221.png

222.png

225.png


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=$harbor_url/$harbor_project_name/$project_name:$tag
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 $port:$port $imageName
echo "容器启动成功"


7)修改代码连接后端微服务服务


6.png

7.png




8)项目测试


4.png

3.png

2.png

1.png

相关文章
|
3月前
|
算法 Java 微服务
【SpringCloud(1)】初识微服务架构:创建一个简单的微服务;java与Spring与微服务;初入RestTemplate
微服务架构是What?? 微服务架构是一种架构模式,它提出将单一应用程序划分为一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。 每个服务允许在其独立的进程中,服务于服务间采用轻量级的通信机制互相协作(通常是Http协议的RESTful API或RPC协议)。 每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据上下文,选择合适的语言、工具对其进行构建
549 126
|
3月前
|
负载均衡 算法 Java
【SpringCloud(2)】微服务注册中心:Eureka、Zookeeper;CAP分析;服务注册与服务发现;单机/集群部署Eureka;连接注册中心
1. 什么是服务治理? SpringCloud封装了Netfix开发的Eureka模块来实现服务治理 在传统pc的远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册
342 0
|
4月前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1978 10
|
3月前
|
负载均衡 Java API
《深入理解Spring》Spring Cloud 构建分布式系统的微服务全家桶
Spring Cloud为微服务架构提供一站式解决方案,涵盖服务注册、配置管理、负载均衡、熔断限流等核心功能,助力开发者构建高可用、易扩展的分布式系统,并持续向云原生演进。
|
4月前
|
监控 安全 Java
Spring Cloud 微服务治理技术详解与实践指南
本文档全面介绍 Spring Cloud 微服务治理框架的核心组件、架构设计和实践应用。作为 Spring 生态系统中构建分布式系统的标准工具箱,Spring Cloud 提供了一套完整的微服务解决方案,涵盖服务发现、配置管理、负载均衡、熔断器等关键功能。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
289 1
|
SpringCloudAlibaba API 开发者
新版-SpringCloud+SpringCloud Alibaba
新版-SpringCloud+SpringCloud Alibaba
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
定时任务在企业应用中至关重要,常用于异步数据处理、自动化运维等场景。在单体应用中,利用Java的`java.util.Timer`或Spring的`@Scheduled`即可轻松实现。然而,进入微服务架构后,任务可能因多节点并发执行而重复。Spring Cloud Alibaba为此发布了Scheduling模块,提供轻量级、高可用的分布式定时任务解决方案,支持防重复执行、分片运行等功能,并可通过`spring-cloud-starter-alibaba-schedulerx`快速集成。用户可选择基于阿里云SchedulerX托管服务或采用本地开源方案(如ShedLock)
428 1
|
10月前
|
负载均衡 Dubbo Java
Spring Cloud Alibaba与Spring Cloud区别和联系?
Spring Cloud Alibaba与Spring Cloud区别和联系?
|
11月前
|
人工智能 SpringCloudAlibaba 自然语言处理
SpringCloud Alibaba AI整合DeepSeek落地AI项目实战
在现代软件开发领域,微服务架构因其灵活性、可扩展性和模块化特性而受到广泛欢迎。微服务架构通过将大型应用程序拆分为多个小型、独立的服务,每个服务运行在其独立的进程中,服务与服务间通过轻量级通信机制(通常是HTTP API)进行通信。这种架构模式有助于提升系统的可维护性、可扩展性和开发效率。
4164 2
|
SpringCloudAlibaba 负载均衡 Dubbo
【SpringCloud Alibaba系列】Dubbo高级特性篇
本章我们介绍Dubbo的常用高级特性,包括序列化、地址缓存、超时与重试机制、多版本、负载均衡。集群容错、服务降级等。
1879 6
【SpringCloud Alibaba系列】Dubbo高级特性篇