Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成

Jenkins+Docker+SpringCloud微服务持续集成

  • Jenkins+Docker+SpringCloud持续集成流程说明
    • SpringCloud微服务源码概述
    • 本地部署
      • SpringCloud微服务部署
    • 使用Dockerfile制作微服务镜像
    • Harbor镜像仓库安装及使用
      • Harbor安装
      • 在Harbor创建用户和项目
      • 把镜像上传到Harbor
      • 从Harbor下载镜像
  • 微服务持续集成
    • 项目代码上传到Gitlab
    • 从Gitlab拉取项目源码
    • 提交到SonarQube代码审查
    • 将微服务打包成jar包
    • 使用Dockerfile编译、生成镜像
    • 上传到Harbor镜像仓库
      • 报错
    • 拉取镜像和发布应用
    • 配置远程部署服务器
      • 编写远程脚本文件
      • 编写Jenkinsfile
    • 更改微服务设置,准备好测试数据
    • 部署前端静态web网站

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

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第1张图片

  1. 开发人员每天把代码提交到Gitlab代码仓库
  2. Jenkins从Gitlab中拉取项目源码,编译并打成jar包,然后构建成Docker镜像,将镜像上传到Harbor私有仓库
  3. Jenkins发送SSH远程命令,让生产部署服务器到Harbor私有仓库拉取镜像到本地,然后创建容器
  4. 最后,用户可以访问到容器

SpringCloud微服务源码概述

  • 项目架构:前后端分离

  • 后端技术栈:SpringBoot+SpringCloud+SpringDataJpa

  • 微服务项目结构:
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第2张图片

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

    • tensquare_user:用户认证数据库,存放用户账户数据。对应tensquare_admin_service微服务
    • tensquare_gathering:活动微服务数据库。对应tensquare_gathering微服务
  • 微服务配置分析:

    • tensquare_eureka
    • tensquare_zuul
    • tensquare_admin_service
    • tensquare_gathering

本地部署

逐一启动微服务

  1. 运行eureka服务器
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第3张图片
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第4张图片
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第5张图片
    通过浏览器进入localhost:10086
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第6张图片

  2. 开启网关zuul
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第7张图片
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第8张图片

  3. 开启权限中心
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第9张图片
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第10张图片

  4. 开启微服务
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第11张图片
    都成功启动
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第12张图片

SpringCloud微服务部署

首先需要导入插件
在pom.xml里添加
在这里插入图片描述

 <plugin>
     <groupId>org.springframework.bootgroupId>
     <artifactId>spring-boot-maven-pluginartifactId>
 plugin>
  1. SpringBoot微服务项目打包
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第13张图片
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第14张图片

    生成的jar包在target下面
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第15张图片
    本地运行微服务的jar包

    java -jar xxx.jar

    我们可以使用cmd运行一下
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第16张图片

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第17张图片

使用Dockerfile制作微服务镜像

安装docker


安装需要的安装包
yum install -y yum-utils

设置镜像仓库
我们用阿里云

yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

更新yum软件包索引
yum makecache fast

安装docker	docker-ce 社区
yum -y install docker-ce docker-ce-cli containerd.io

启动docker
systemctl start docker

查看版本
docker version

将eureka的jar包上传至服务器

mkdir /root/eureka
mv tensquare_eureka_server-1.0-SNAPSHOT.jar /root/eureka/

cd /root/eureka/
vim Dockerfile

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

docker build --build-arg JAR_FILE=tensquare_eureka_server-1.0-SNAPSHOT.jar -t eureka:v1 

构建完成之后查看

[root@jenkins eureka]# docker images
REPOSITORY   TAG            IMAGE ID       CREATED         SIZE
eureka       v1             255f6b6c7c53   4 seconds ago   150MB
openjdk      8-jdk-alpine   a3562aa0b991   2 years ago     105MB

验证镜像是否成功
docker run -di -p 10086:10086 eureka:v1

查看日志
docker logs -f 容器id

浏览器访问
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第18张图片

Harbor镜像仓库安装及使用

  • Harbor(港口,港湾)是一个用于存储和分发Docker镜像的企业级Registry服务器。
  • 除了Harbor这个私有镜像仓库之外,还有Docker官方提供的Registry。相对Registry,Harbor具有很多优势:
    1. 提供分层传输机制,优化网络传输
      Docker镜像是是分层的,而如果每次传输都使用全量文件(所以用FTP的方式并不适合),显然不经济。必须提供识别分层传输的机制,以层的UUID为标识,确定传输的对象。
    2. 提供WEB界面,优化用户体验
      只用镜像的名字来进行上传下载显然很不方便,需要有一个用户界面可以支持登陆、搜索功能,包括区分公有、私有镜像。
    3. 支持水平扩展集群
      当有用户对镜像的上传下载操作集中在某服务器,需要对相应的访问压力作分解。
    4. 良好的安全机制
      企业中的开发团队有很多不同的职位,对于不同的职位人员,分配不同的权限,具有更好的安全性。

Harbor安装

我们在harbor服务器上进行安装

安装docker和compose

安装需要的安装包
yum install -y yum-utils

设置镜像仓库
我们用阿里云

yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

安装docker
yum install docker-ce docker-ce-cli containerd.io

systemctl enable docker --now

下载安装compose
curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m) > /usr/local/bin/docker-compose  

授权
chmod +x /usr/local/bin/docker-compose 

查看版本
docker-compose version

安装harbor
下载地址

下载完毕之后上传至服务器

tar xf harbor-offline-installer-v1.9.2.tgz -C /usr/local

cd /usr/local/harbor

修改harbor.yml 文件里面的hostname 改成本机地址
vim harbor.yml
hostname: 192.168.188.103

端口改成85 就不会与80冲突
port: 85

拉取镜像命令
./prepare 

安装
./install.sh

当完成安装后,即可通过本机地址进行浏览器的访问

账户名为admin,密码默认为Harbor12345
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第19张图片

在Harbor创建用户和项目

创建项目

Harbor的项目分为公开和私有的:

  • 公开项目:所有用户都可以访问,通常存放公共的镜像,默认有一个library公开项目。
  • 私有项目:只有授权用户才可以访问,通常存放项目本身的镜像。

我们可以为微服务项目创建一个新的项目

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第20张图片

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第21张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第22张图片
创建用户
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第23张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第24张图片
密码Xiaotian123

给私有项目分配用户
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第25张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第26张图片

把镜像上传到Harbor

  1. 给镜像打上标签

    [root@jenkins eureka]# docker images
    REPOSITORY   TAG            IMAGE ID       CREATED          SIZE
    eureka       v1             255f6b6c7c53   32 minutes ago   150MB
    openjdk      8-jdk-alpine   a3562aa0b991   2 years ago      105MB
    
    docker tag eureka:v1 192.168.188.103:85/tensquare/eureka:v1
    
    [root@jenkins eureka]# docker images
    REPOSITORY                           TAG            IMAGE ID       CREATED          SIZE
    192.168.188.103:85/tensquare/eureka   v1             255f6b6c7c53   33 minutes ago   150MB
    eureka                               v1             255f6b6c7c53   33 minutes ago   150MB
    openjdk                              8-jdk-alpine   a3562aa0b991   2 years ago      105MB
    
  2. 把Harbor地址加入到Docker信任列表

    vi /etc/docker/daemon.json
    
    {
           
    "registry-mirrors": ["https://zydiol88.mirror.aliyuncs.com"],
    "insecure-registries": ["192.168.188.103:85"]
    }
    
    重启docker
    
  3. 登录Harbor

    docker login 192.168.188.103:85 -u maomao -p Xiaotian123
    
  4. 推送镜像

    docker push 192.168.188.103:85/tensquare/eureka:v1
    

仓库里面有了上传的镜像
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第27张图片

从Harbor下载镜像

在192.168.188.102服务器下载镜像

vi /etc/docker/daemon.json

{
     
"registry-mirrors": ["https://zydiol88.mirror.aliyuncs.com"],
"insecure-registries": ["192.168.188.103:85"]
}

systemctl daemon-reload 
systemctl restart docker

先登录,再从Harbor下载镜像

[root@tomcat ~]# docker login 192.168.188.103:85 -u maomao -p Xiaotian123 
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

拉取镜像
docker pull 192.168.188.103:85/tensquare/eureka:v1

docker images

微服务持续集成

项目代码上传到Gitlab

上传后台微服务和前端web网站代码

首先去gitlab上面创建项目
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第28张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第29张图片
我们在这个组里就有新建的两个项目
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第30张图片
上传代码,通过IDEA操作

Add添加到本地缓冲区
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第31张图片
将代码提交到本地代码仓库
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第32张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第33张图片
新建一个仓库地址
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第34张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第35张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第36张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第37张图片

推送代码至仓库

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第38张图片
项目已经成功提交
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第39张图片
前端代码我们通过Git小乌龟来上传
安装地址

在代码目录 右键 选择在这创建版本库
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第40张图片

右键 选择commit
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第41张图片

选择推送 将代码推送远程仓库
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第42张图片

设置仓库地址
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第43张图片
在这里插入图片描述
填写仓库用户和密码
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第44张图片

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第45张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第46张图片
到此为止 代码都已经上传至仓库

从Gitlab拉取项目源码

我们进入jenkins构建后端流水线项目
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第47张图片
添加参数
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第48张图片

选择SCM 脚本上传至仓库
配置git地址 通过ssh拉取
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第49张图片
打开IDEA 在工程根目录下面创建一个Jenkinsfile

打开流水线语法
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第50张图片
帮助我们生成脚本
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第51张图片
我们可以定义变量

//git凭证ID
def git_auth = "41580d48-d4c3-4116-9a71-4d4d777c5753"
// git的url地址
def git_url = "[email protected]:maomao_group/tensquare_back.git"


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

}

上传Jenkinsfile文件
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第52张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第53张图片
开始构建项目
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第54张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第55张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第56张图片
注意 脚本里面一定要注意格式和语法,自己因为冒号的原因,错了三次才改正过来

提交到SonarQube代码审查

在tensquare_back项目里,添加两个参数
这个参数选择选项参数(Choice Parameter)
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第57张图片
添加需要选择审查的名字
在这里插入图片描述

这时候构建就可以选择需要审查的代码
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第58张图片
接下来配置sonarkube文件

在eureka_server根目录创建sonar-project.properties
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第59张图片
eureka_server

# must be unique in a given SonarQube instance
sonar.projectKey=tensquare_eureka_server
# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.
sonar.projectName=tensquare_eureka_server
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

然后再相应的目录里添加不同的sonar-project.properties

zull

# must be unique in a given SonarQube instance
sonar.projectKey=tensquare_zuul
# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.
sonar.projectName=tensquare_zuul
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

admin_service

# must be unique in a given SonarQube instance
sonar.projectKey=tensquare_admin_service
# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.
sonar.projectName=tensquare_admin_service
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

gathering

# must be unique in a given SonarQube instance
sonar.projectKey=tensquare_gathering
# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.
sonar.projectName=tensquare_gathering
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

修改Jenkinsfile脚本

//git凭证ID
def git_auth = "41580d48-d4c3-4116-9a71-4d4d777c5753"
// git的url地址
def git_url = "[email protected]:maomao_group/tensquare_back.git"


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

}

push代码至仓库 然后构建项目
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第60张图片
查看控制台输出

开始审查代码
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第61张图片
构建成功
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第62张图片
来到sonarkube后台查看审查结果
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第63张图片
然后我们把剩下三个代码也进行审查
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第64张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第65张图片
没有问题
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第66张图片

将微服务打包成jar包

第一步 需要对一个公共的子工程进程编译,安装

在Jenkinsfile里添加一个步骤

//git凭证ID
def git_auth = "41580d48-d4c3-4116-9a71-4d4d777c5753"
// git的url地址
def git_url = "[email protected]:maomao_group/tensquare_back.git"


node {
     
   stage('拉取代码') {
     
      checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
   }
   stage('代码审查') {
     
        //定义了当前Jenkins的SonarQubeScanner工具环境     在全局工具配置里查看
        def scannerHome = tool 'sonar-scanner'
        //引用当前JenkinsSonarQube环境    在系统配置里查看
        withSonarQubeEnv('sonarqube') {
     
             sh """
                    cd ${project_name}
                    ${scannerHome}/bin/sonar-scanner
                """
        }
   }
   stage('编译,安装公共子工程') {
     
        sh "mvn -f tensquare_common clean install"
   }

}

将脚本上传至git仓库,再尝试进行一次构建
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第67张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第68张图片
进行打包
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第69张图片
构建成功
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第70张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第71张图片

如果失败的话,进入IDEA
将tensquare_parent父工程里面的 spring-boot-maven插件移走 移到需要项目打包的项目里去

tensquare_common子工程不需要这个插件

只需要将插件加入tensquare_eureka_server、tensquare_admin_service、tensquare_gathering、tensquare_zuul

<build>
       <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>

调整好之后,继续编写Jenkinsfile,需要打包其他微服务了

//git凭证ID
def git_auth = "41580d48-d4c3-4116-9a71-4d4d777c5753"
// git的url地址
def git_url = "[email protected]:maomao_group/tensquare_back.git"


node {
     
   stage('拉取代码') {
     
      checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
   }
   stage('代码审查') {
     
        //定义了当前Jenkins的SonarQubeScanner工具环境     在全局工具配置里查看
        def scannerHome = tool 'sonar-scanner'
        //引用当前JenkinsSonarQube环境    在系统配置里查看
        withSonarQubeEnv('sonarqube') {
     
             sh """
                    cd ${project_name}
                    ${scannerHome}/bin/sonar-scanner
                """
        }
   }
   stage('编译,安装公共子工程') {
     
        sh "mvn -f tensquare_common clean install"
   }
   // 这里project_name就是参数 选择对谁打包
   stage('编译,安装公共子工程') {
     
           sh "mvn -f ${project_name} clean package"
   }

}

对eureka服务进行打包
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第72张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第73张图片
通过目录也可以看见 tensquare_admin_service没有进行打包
tensquare_eureka_server进行了打包 target下有jar包
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第74张图片
接下来将其它三个微服务以同样方式打包
但是在打包tensquare_zuul报错了
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第75张图片
因为网关依赖父工程,但是仓库里的父工程没有

因此我们需要手动将父工程pom.xml文件传到Jenkins服务器里

在这里插入图片描述

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第76张图片
再次重新构建
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第77张图片
这次找到父工程的pom文件之后 打包成功
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第78张图片
然后将剩下两个微服务打包构建
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第79张图片
除了第二次打包网关失败 其余都成功了

使用Dockerfile编译、生成镜像

利用dockerfile-maven-plugin插件构建Docker镜像

在每个微服务项目的pom.xml加入dockerfile-maven-plugin插件

我们可以在之前spring-boot-maven-plugin插件下面添加dockerfile-maven-plugin插件

<build>
       <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
            <plugin>
                <groupId>com.spotifygroupId>
                <artifactId>dockerfile-maven-pluginartifactId>
                <version>1.3.6version>
                <configuration>
                    <repository>${project.artifactId}repository>
                    <buildArgs>
                        <JAR_FILE>target/${project.build.finalName}.jarJAR_FILE>
                    buildArgs>
                configuration>
            plugin>
        plugins>
    build>

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第80张图片

在每个微服务里创建一个Dockerfile文件
在这里插入图片描述

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

修改Jenkinsfile 添加dockerfile:build命令

//git凭证ID
def git_auth = "41580d48-d4c3-4116-9a71-4d4d777c5753"
// git的url地址
def git_url = "[email protected]:maomao_group/tensquare_back.git"


node {
     
   stage('拉取代码') {
     
      checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
   }
   stage('代码审查') {
     
        //定义了当前Jenkins的SonarQubeScanner工具环境     在全局工具配置里查看
        def scannerHome = tool 'sonar-scanner'
        //引用当前JenkinsSonarQube环境    在系统配置里查看
        withSonarQubeEnv('sonarqube') {
     
             sh """
                    cd ${project_name}
                    ${scannerHome}/bin/sonar-scanner
                """
        }
   }
   stage('编译,安装公共子工程') {
     
        sh "mvn -f tensquare_common clean install"
   }
   stage('编译,安装公共子工程') {
     
           sh "mvn -f ${project_name} clean package dockerfile:build"
   }

}

然后对eureka_server进行构建
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第81张图片
进行镜像的制作
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第82张图片
执行Dockerfile里写的步骤
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第83张图片
最后成功
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第84张图片
查看镜像,已经创建成功
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第85张图片
接下来把其他微服务也构建成镜像,需要写Dockerfile和添加插件

tensquare_zuul

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

tensquare_admin_service

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

tensquare_gathering

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

上传代码之后进行构建

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第86张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第87张图片
四个微服务的镜像都构建成功

上传到Harbor镜像仓库

修改Jenkinsfile构建脚本

//git凭证ID
def git_auth = "41580d48-d4c3-4116-9a71-4d4d777c5753"
// git的url地址
def git_url = "[email protected]:maomao_group/tensquare_back.git"
// 镜像的版本号
def tag = "latest"
// Harbor的url地址
def harbor_url = "192.168.188.103:85"
// 镜像库项目名称
def harbor_project = "tensquare"

node {
     
   stage('拉取代码') {
     
      checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
   }
   stage('代码审查') {
     
        //定义了当前Jenkins的SonarQubeScanner工具环境     在全局工具配置里查看
        def scannerHome = tool 'sonar-scanner'
        //引用当前JenkinsSonarQube环境    在系统配置里查看
        withSonarQubeEnv('sonarqube') {
     
             sh """
                    cd ${project_name}
                    ${scannerHome}/bin/sonar-scanner
                """
        }
   }
   stage('编译,安装公共子工程') {
     
        sh "mvn -f tensquare_common clean install"
   }
   stage('编译,安装公共子工程,上传镜像') {
     
           sh "mvn -f ${project_name} clean package dockerfile:build"

           //定义镜像名称
           def imageName = "${project_name}:${tag}"

           //对镜像打上标签
           sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"
   }

}

测试一下生成的镜像能否打上标签
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第88张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第89张图片

添加一个harbor用户凭据
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第90张图片
再次进去查看 将生成的id复制
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第91张图片
4135b3f5-a3eb-436e-a6ef-fe096098bb4f

进入流水线语法
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第92张图片

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第93张图片
将流水线生成的语法稍作改变
增加变量

// git凭证ID
def git_auth = "41580d48-d4c3-4116-9a71-4d4d777c5753"
// git的url地址
def git_url = "[email protected]:maomao_group/tensquare_back.git"
// 镜像的版本号
def tag = "latest"
// Harbor的url地址
def harbor_url = "192.168.188.103:85"
// 镜像库项目名称
def harbor_project = "tensquare"
// Harbor的登录凭据ID
def harbor_auth = "4135b3f5-a3eb-436e-a6ef-fe096098bb4f"

node {
     
   stage('拉取代码') {
     
      checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
   }
   stage('代码审查') {
     
        //定义了当前Jenkins的SonarQubeScanner工具环境     在全局工具配置里查看
        def scannerHome = tool 'sonar-scanner'
        //引用当前JenkinsSonarQube环境    在系统配置里查看
        withSonarQubeEnv('sonarqube') {
     
             sh """
                    cd ${project_name}
                    ${scannerHome}/bin/sonar-scanner
                """
        }
   }
   stage('编译,安装公共子工程') {
     
        sh "mvn -f tensquare_common clean install"
   }
   stage('编译,安装公共子工程,上传镜像') {
     

         sh "mvn -f ${project_name} clean package dockerfile:build"

         //定义镜像名称
         def imageName = "${project_name}:${tag}"

         //对镜像打上标签
         sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"

         //把镜像推送到Harbor
         withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
     
             // 登录到Harbor
             sh "docker login -u ${username} -p ${password} ${harbor_url}"

             // 镜像上传
             sh "docker push ${harbor_url}/${harbor_project}/${imageName}"

             sh "echo 镜像上传成功了"
         }

   }

}

上传镜像成功
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第94张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第95张图片

报错

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第96张图片

这一步有两个小细节错了 害得我弄了一个多小时才找出来,气得要死

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第97张图片
这里显示我docker tag 命令参数多了
后面仔细检测发现这里多了一个空格
在这里插入图片描述
各种排查,仍然有空格,后面在任务配置里找到选项参数
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第98张图片
发现这里面的选项前面打了空格,导致脚本读取参数也包含了空格

第二个错误是因为把username写成了usrname
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第99张图片

拉取镜像和发布应用

安装Publish Over SSH插件 可以实现远程发送Shell命令
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第100张图片

配置远程部署服务器

将jenkins服务器的公钥拷贝到远程tomcat服务器
ssh-copy-id 192.168.188.107

在jenkins进入系统配置,找到Publish over SSH

Path to key 填私钥存放的位置 /root/.ssh/id_rsa

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第101张图片
下面点击新增
Hostname 填 远程部署项目的主机ip
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第102张图片
接下来要写Jenkinsfile脚本,首先去流水线语法
找到这个 可以帮我们产生一些远程连接的脚本
在这里插入图片描述
ssh server 选择我们之前传公钥的服务器
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第103张图片
其他现在都留空,点击生成流水线脚本
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第104张图片
这段就是复制下来的脚本

sshPublisher(publishers: [sshPublisherDesc(configName: 'tomcat_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
  • execCommand就是在远程服务器上执行的命令,我们让它执行一个shell脚本,shell脚本就可以帮助我们完成部署

  • 因为我们微服务的端口是不相同的,所以还要在流水线任务里面添加新的端口参数
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第105张图片
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第106张图片

编写远程脚本文件

进入tomcat服务器
[root@tomcat ~]# mkdir /opt/jenkins_shell
[root@tomcat ~]# cd /opt/jenkins_shell/
[root@tomcat jenkins_shell]# vim deploy.sh

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

imageName=$harbor_url/$harbor_project/$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 maomao -p Xiaotian123 $harbor_url

# 下载镜像
docker pull $imageName

# 启动容器
docker run -di -p $port:$port $imageName

echo "容器启动成功"
然后给脚本加上执行权限
chmod +x deploy.sh

编写Jenkinsfile

// git凭证ID
def git_auth = "41580d48-d4c3-4116-9a71-4d4d777c5753"
// git的url地址
def git_url = "[email protected]:maomao_group/tensquare_back.git"
// 镜像的版本号
def tag = "latest"
// Harbor的url地址
def harbor_url = "192.168.188.106:85"
// 镜像库项目名称
def harbor_project = "tensquare"
// Harbor的登录凭据ID
def harbor_auth = "c0e6642d-bab9-4978-be45-955e5130fae2"

node {
     
   stage('拉取代码') {
     
      checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
   }
   stage('代码审查') {
     
        //定义了当前Jenkins的SonarQubeScanner工具环境     在全局工具配置里查看
        def scannerHome = tool 'sonar-scanner'
        //引用当前JenkinsSonarQube环境    在系统配置里查看
        withSonarQubeEnv('sonarqube') {
     
             sh """
                    cd ${project_name}
                    ${scannerHome}/bin/sonar-scanner
                """
        }
   }
   stage('编译,安装公共子工程') {
     
        sh "mvn -f tensquare_common clean install"
   }
   stage('编译,安装公共子工程,上传镜像') {
     

         sh "mvn -f ${project_name} clean package dockerfile:build"

         //定义镜像名称
         def imageName = "${project_name}:${tag}"

         //对镜像打上标签
         sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"

         //把镜像推送到Harbor
         withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
     
             // 登录到Harbor
             sh "docker login -u ${username} -p ${password} ${harbor_url}"

             // 镜像上传
             sh "docker push ${harbor_url}/${harbor_project}/${imageName}"

             sh "echo 镜像上传成功啦"
         }

         // 部署项目
         sshPublisher(publishers: [sshPublisherDesc(configName: 'tomcat_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh $harbor_url $harbor_project $project_name $tag $port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
   }

}

上传代码之后构建项目
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第107张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第108张图片
开始远程登录服务器执行脚本
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第109张图片
在部署服务器上查看镜像和容器
在这里插入图片描述

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第110张图片

更改微服务设置,准备好测试数据

  • eureka配置
    修改ip地址为我们部署的服务器地址
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第111张图片
  • zuul网关
    也是修改eruka的ip地址
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第112张图片
  • admin_service权限中心
    这里需要修改数据库相关信息(我们选择sonarqube服务器上的mysql作为后端数据库,此数据库在jenkins服务器上)
  • 因此我们需要去mysql里面进行授权
授权root账户能够在所以客户端登录
grant all privileges on *.* to 'root'@'%' identified by '123';

刷新权限
flush privileges;

利用Navicat 测试
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第113张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第114张图片
修改配置
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第115张图片

  • gathering
    也是修改数据库和ip
    Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第116张图片

最后将所有更新的配置上传代码仓库
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第117张图片
然后导入mysql数据
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第118张图片
最后把剩下的三个微服务也构建成容器
这里需要注意的是要改变端口
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第119张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第120张图片
查看容器
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第121张图片
通过浏览器查看Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第122张图片

部署前端静态web网站

在tomcat服务器上进行

yum install -y epel-release

yum -y install nginx

修改nginx的端口,默认80,改为9090

vim /etc/nginx/nginx.conf

server {
     
        listen       9090 default_server;
        listen       [::]:9090 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

启动nginx
systemctl enable nginx --now

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第123张图片
安装NodeJS插件
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第124张图片
Jenkins在全局工具配置里配置Nginx服务器

找到NodeJS 选择一个版本 保存
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第125张图片

创建前端流水线项目
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第126张图片
首先添加分支参数
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第127张图片

编写流水线脚本

//gitlab的凭证 
def git_auth = "41580d48-d4c3-4116-9a71-4d4d777c5753"
 node {
      stage('拉取代码') {
     
	checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']],
	doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [],
	userRemoteConfigs: [[credentialsId: "${git_auth}", url:
	'[email protected]:maomao_group/tensquare_front.git']]]) 
	   }
	   stage('打包,部署网站') {
     
	   //使用NodeJS的npm进行打包
	   nodejs('nodejs12'){
     
			sh '''
				npm install 
				npm run build 
			''' 
		}
		
		//=====以下为远程调用进行项目部署========
		sshPublisher(publishers: [sshPublisherDesc(configName: 'tomcat_server',
		transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '',
		execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes:
		false, patternSeparator: '[, ]+', remoteDirectory: '/usr/share/nginx/html',
		remoteDirectorySDF: false, removePrefix: 'dist', sourceFiles: 'dist/**')],
		usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
			}	
		}

注意里面的git_auth 凭据id需要去jenkins里面找
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第128张图片
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第129张图片
构建成功
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第130张图片
通过浏览器登录ip+9090端口
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第131张图片
登录
Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第132张图片
查询到了数据库的信息,因此证明前端页面和后端连接成功

Jenkins—— Jenkins+Docker+SpringCloud微服务持续集成_第133张图片
至此我们的Jenkins+Docker+SpringCloud微服务持续集成就搭建完成了,剩下的就是对其的优化了

你可能感兴趣的:(CI/CD,jenkins,ci/cd,docker,java,linux)