五、Jenkins、Docker、SpringClound持续集成

Jenkins、Docker、SpringClound持续集成

  • 一、部署介绍
    • 1.部署图
    • 2.微服务项目结构
    • 3.项目启动顺序
  • 二、微服务项目在Windows运行
    • 1.配置java、maven环境
    • 2.初始化数据库表/数据
      • 2.1 tensquare_gathering服务表
      • 2.2 tensquare_gathering服务表
    • 3.启动微服务
    • 4.微服务接口测试
      • 4.1 获取用户token
      • 4.2 获取所有活动
  • 三、本地打包和运行微服务
    • 1.安装SpringBoot打包库
    • 2.打包微服务
    • 3.本地运行jar包
    • 4.打包遇到的坑
  • 四、打包前端代码
  • 五、使用Dockerfile制作微服务镜像
    • 1.Dockerfile常见命令
    • 2.编写eureka服务Dockerfile
      • 2.1 将jar包上传linux
      • 2.2 编写Dockerfile
      • 2.3 构建镜像
      • 2.4 启动容器
      • 2.5 访问容器
  • 六、Docker部署Harbor
    • 1.安装
    • 2.访问
    • 3.创建项目
    • 4.创建用户
    • 5.给用户分配项目
    • 6.本地镜像上传
      • 6.1 给镜像打上标签
      • 6.2 将harbor地址添加到Docker白名单
      • 6.3 命令行登录harbor
      • 6.4 推送镜像
      • 6.5 从Harbor下载镜像
        • 6.5.1 命令行登录Harbor
        • 6.5.2 拉取镜像
  • 七、微服务持续集成-案例
    • 1.项目上传到gitlab
      • 1.1 创建git项目
      • 1.2 IDEA上传后端项目
        • 1.2.1 配置git程序
        • 1.2.2 配置GitLab
        • 1.2.3 上传代码
      • 1.3 Git上传前端代码
    • 2.在Jenkins从GitLab拉取源码
      • 2.1 创建Jenkins微服务项目
        • 2.1.1 创建后端Jenkins项目
        • 2.1.2 编写Jenkins脚本文件
        • 2.1.3 编写每个微服务harbor配置
          • 2.1.3.1 zuul
          • 2.1.3.2 eureka
          • 2.1.3.3 admin_service
          • 2.1.3.3 gathering
        • 2.1.4 流水线添加harbor
    • 3.微服务打包
      • 3.1 Jenkins环境准备
        • 3.1.1 安装项目java环境
        • 3.1.2 安装maven环境
        • 3.1.3 将父工程依赖文件放入maven环境
        • 3.1.4 docker环境
      • 3.2 对公共子工程打包
      • 3.3 对微服务打包
    • 4.使用Dockerfile编译、生成镜像
      • 4.1 配置构建docker的插件
      • 4.2 配置Dockerfile
    • 5.上传到Harbor镜像库
    • 6.拉取镜像和发布应用
      • 6.1 Jenkins安装发布插件
      • 6.2 ssh公钥配置
        • 6.2.1 公钥传输
        • 6.2.2 jenkins公钥配置
        • 6.2.2 jenkins项目构建添加端口参数
        • 6.2.3 Jenkinsfile添加部署命令
        • 6.2.3 编写sh部署脚本
      • 6.3 导入微服务的表和数据
      • 6.4 修改所有微服务注册中心配置地址
      • 6.4 按顺序构建docker并自动部署
      • 6.5 测试接口
    • 7.部署前端静态web网站
      • 7.1 部署服务器安装nginx
      • 7.2 Jenkins配置NodeJS
        • 7.2.1 安装NodeJS插件
        • 7.2.2 安装NodeJS版本
      • 7.3 创建前端流水线
      • 7.4 修改前端文件BASE_API地址
      • 7.5 Jenkins构建
  • 八、微服务持续集成-优化
    • 1.存在的问题
    • 2.集群版eureka配置
      • 2.1 eureka微服务配置文件
      • 2.2 其他微服务配置文件
      • 2.3 Jenkins多选类型参数
        • 2.3.1 安装多选框组件
        • 2.3.2 创建流水线项目
        • 2.3.3 添加微服务项目多选参数
        • 2.3.4 添加部署服务器多选参数
      • 2.4 Jenkinsfile编写
      • 2.5 部署sh脚本编写
  • 八、Nginx+zuul集群实现高可用网关
    • 1.安装nginx
    • 2.修改nginx配置
    • 3.重启nginx

一、部署介绍

1.部署图

2.微服务项目结构

  1. tensquare_admin_service:权限认证服务(登录、注销、token分发等)
  2. tensquare_common:工具类
  3. tensquare_eureka_server:单机版eureka服务
  4. tensquare_gathering:业务服务
  5. tensquare_zuul:zuul网关服务

3.项目启动顺序

  1. tensquare_eureka_server
  2. tensquare_zuul
  3. tensquare_admin_service
  4. tensquare_gathering

二、微服务项目在Windows运行

1.配置java、maven环境

  • IDEA配置java、maven环境
  • 配置好环境后,使用maven下载好所有的依赖包

2.初始化数据库表/数据

2.1 tensquare_gathering服务表

/*
SQLyog 企业版 - MySQL GUI v8.14 
MySQL - 5.7.4-m14 : Database - tensquare_gathering
*********************************************************************
*/

/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`tensquare_gathering` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `tensquare_gathering`;

/*Table structure for table `tb_city` */

DROP TABLE IF EXISTS `tb_city`;

CREATE TABLE `tb_city` (
  `id` varchar(20) NOT NULL COMMENT 'ID',
  `name` varchar(20) DEFAULT NULL COMMENT '城市名称',
  `ishot` varchar(1) DEFAULT NULL COMMENT '是否热门',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='城市';

/*Data for the table `tb_city` */

insert  into `tb_city`(`id`,`name`,`ishot`) values ('1','北京','1'),('2','上海','1'),('3','广州','1'),('4','深圳','1'),('5','天津','0'),('6','重庆','0'),('7','西安','0');

/*Table structure for table `tb_gathering` */

DROP TABLE IF EXISTS `tb_gathering`;

CREATE TABLE `tb_gathering` (
  `id` varchar(20) NOT NULL COMMENT '编号',
  `name` varchar(100) DEFAULT NULL COMMENT '活动名称',
  `summary` text COMMENT '大会简介',
  `detail` text COMMENT '详细说明',
  `sponsor` varchar(100) DEFAULT NULL COMMENT '主办方',
  `image` varchar(100) DEFAULT NULL COMMENT '活动图片',
  `starttime` date DEFAULT NULL COMMENT '开始时间',
  `endtime` date DEFAULT NULL COMMENT '截止时间',
  `address` varchar(100) DEFAULT NULL COMMENT '举办地点',
  `enrolltime` datetime DEFAULT NULL COMMENT '报名截止',
  `state` varchar(1) DEFAULT NULL COMMENT '是否可见',
  `city` varchar(20) DEFAULT NULL COMMENT '城市',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='活动';

/*Data for the table `tb_gathering` */

insert  into `tb_gathering`(`id`,`name`,`summary`,`detail`,`sponsor`,`image`,`starttime`,`endtime`,`address`,`enrolltime`,`state`,`city`) values ('1','测试活动6666','喝茶看电影,不亦乐乎','喝茶看电影,不亦乐乎','黑马程序员',NULL,'2019-11-01','2019-11-01','广州市黑马程序员',NULL,'1','6'),('94377594140','aaaa',NULL,NULL,NULL,NULL,'2019-11-01','2019-11-01',NULL,NULL,'1','1'),('943776146707845','aaaa',NULL,NULL,'ssss',NULL,'2019-11-01','2019-11-01','cccc',NULL,'1','1'),('943776663576121344','aaaa',NULL,NULL,NULL,NULL,'2019-11-01','2019-11-01',NULL,NULL,'1','2'),('943783521749700608','2342423',NULL,NULL,'23454534',NULL,'2019-11-01','2019-11-01','545435435',NULL,'1','2'),('944085821768732672','JAVAEE茶话会',NULL,NULL,'传智',NULL,'2019-11-01','2019-11-01','金燕龙',NULL,'1','2'),('944086086991351808','是',NULL,NULL,'11',NULL,'2019-11-01','2019-11-01','11',NULL,'1','3'),('944090372710207488','大讨论',NULL,NULL,'小马',NULL,'2019-11-01','2019-11-01','消息',NULL,'1','3'),('944105652622594048','测试测试',NULL,NULL,'测试者',NULL,'2019-11-01','2019-11-01','测试地址',NULL,'1','4'),('945227340642914304','111',NULL,NULL,'222',NULL,'2019-11-01','2019-11-01','333',NULL,'1','5'),('945227678527655936','111',NULL,NULL,'222',NULL,'2019-11-01','2019-11-01','333',NULL,'1','5'),('945235087564345344','啊啊',NULL,NULL,'1',NULL,'2019-11-01','2019-11-01','1',NULL,'1','1'),('945235534329024512','1',NULL,NULL,'1',NULL,'2019-11-01','2019-11-01','1',NULL,'1','2'),('945235859786043392','1',NULL,NULL,'1',NULL,'2019-11-01','2019-11-01','1',NULL,'1','3');
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

2.2 tensquare_gathering服务表

/*
SQLyog 企业版 - MySQL GUI v8.14 
MySQL - 5.7.4-m14 : Database - tensquare_user
*********************************************************************
*/

/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`tensquare_user` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `tensquare_user`;

/*Table structure for table `tb_admin` */

DROP TABLE IF EXISTS `tb_admin`;

CREATE TABLE `tb_admin` (
  `id` varchar(20) NOT NULL COMMENT 'ID',
  `loginname` varchar(100) DEFAULT NULL COMMENT '登陆名称',
  `password` varchar(100) DEFAULT NULL COMMENT '密码',
  `state` varchar(1) DEFAULT NULL COMMENT '状态',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='管理员';

/*Data for the table `tb_admin` */

insert  into `tb_admin`(`id`,`loginname`,`password`,`state`) values ('1194281533230419968','admin','$2a$10$PhnLmwA7QarH8M/Wc52Mfekoyqw74Vp619M2p2dnxq0Ltz6xXTWJu','1');

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

3.启动微服务

按顺序执行以下服务的Application文件:
tensquare_eureka_server
tensquare_zuul
tensquare_admin_service
tensquare_gathering
在这里插入图片描述

  • 查看注册中心
    在这里插入图片描述

4.微服务接口测试

4.1 获取用户token

  • Method:POST
  • URL:http://localhost:10020/admin/admin/login
  • Payload:
{"loginname": "admin", "password": "123456"}
  • Response:
{
    "flag": true,
    "code": 20000,
    "message": "管理员登录成功",
    "data": {
        "roles": "admin",
        "name": "admin",
        "id": "1194281533230419968",
        "token": "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMTk0MjgxNTMzMjMwNDE5OTY4Iiwic3ViIjoiYWRtaW4iLCJpYXQiOjE3MTIzOTg5NDQsInJvbGVzIjoiYWRtaW4iLCJleHAiOjE3MTI0MDA3NDR9.59JOUrd8E4YlEZwZL3n-nxyOIL620cT2YqjA61N1sRg"
    }
}

4.2 获取所有活动

  • Method:GET
  • URL:http://localhost:10020/gathering/gathering
  • Header
token:eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMTk0MjgxNTMzMjMwNDE5OTY4Iiwic3ViIjoiYWRtaW4iLCJpYXQiOjE3MTIzOTg5NDQsInJvbGVzIjoiYWRtaW4iLCJleHAiOjE3MTI0MDA3NDR9.59JOUrd8E4YlEZwZL3n-nxyOIL620cT2YqjA61N1sRg

在这里插入图片描述

三、本地打包和运行微服务

1.安装SpringBoot打包库

  • 如果不使用下面的插件,那么打包的jar包是不包含依赖包。
  • 在父工程下的pom.xml写入下面的库
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

在这里插入图片描述

2.打包微服务

如果用的IDEA 2020,那么maven需要用3.6.3,否则会报错

  • 总共有四个微服务,最终打包后有4个jar包
  • 四个微服务都是如下图的操作
    在这里插入图片描述

3.本地运行jar包

  • jar -r xxx.jar

4.打包遇到的坑

  • 在没有主文件的工程,在pom.xml需要加入以下
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <executable>true</executable>
                </configuration>
                <executions>
                    <execution>
                        <phase>none</phase>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

四、打包前端代码

  • 技术栈:NodeJS+VueJS+ElementUI
# 1.本地运行
npm run dev
# 2.打包静态web网站
npm run build
# 打包后,产生dist目录的静态文件
# 3.部署到nginx服务器把dist目录的静态文件拷贝到nginx的html目录,启动nginx

五、使用Dockerfile制作微服务镜像

1.Dockerfile常见命令

命令作用
FROM image_name:tag
MAINTAINER user_name声明镜像的作者
ENV key value设置环境变量 (可以写多条)
RUN command编译镜像时运行的脚本(可以写多条)
CMD设置容器的启动命令
ENTRYPOINT设置容器的入口程序
ADD source_dir/file dest_dir/file将宿主机的文件复制到容器内,如果是一个压缩文件,将会在复制后自动解压
COPY source_dir/file dest_dir/file和ADD相似,但是如果有压缩文件并不能解压
WORKDIR path_dir设置工作目录
ARG设置编译镜像时加入的参数
VOLUMN设置容器的挂载卷
  • RUN、CMD、ENTRYPOINT的区别?
    • RUN:用于指定 docker build 过程中要运行的命令,即是创建 Docker 镜像(image)的步骤
    • CMD:设置容器的启动命令, Dockerfile 中只能有一条 CMD 命令,如果写了多条则 后一条生效,CMD不支持接收docker run的参数。
    • ENTRYPOINT:入口程序是容器启动时执行的程序, docker run 中 后的命令将作为参数传递给入口程序 ,ENTRYPOINY类似于 CMD 指令,但可以接收docker run的参数 。

2.编写eureka服务Dockerfile

  • 其他服务和eureka服务的镜像构建步骤是一样的。

2.1 将jar包上传linux

2.2 编写Dockerfile

FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 10086
ENTRYPOINT ["java", "-jar", "/app.jar"]
  • 参数解析:
    • FROM openjdk:8-jdk-alpine:拉取openjdk:8-jdk-alpine作为基础镜像
    • ARG JAR_FILE:定义一个JAR_FILE参数,需要外部传入
    • COPY ${JAR_FILE} app.jar:拷贝一个文件,命名为app.jar
    • EXPOSE 10086:暴露10086端口
    • EXTRYPOINT ["java", "-jar", "/app.jar"]:设置java项目启动命令

2.3 构建镜像

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

在这里插入图片描述

2.4 启动容器

docker run -i --name=eureka -p 10086:10086 eureka:v1

2.5 访问容器

  • http://192.168.86.128:10086

六、Docker部署Harbor

1.安装

  • Harbor是基于docker的,所以需要安装docker和docker-compose。
  • docker和docker-compose版本要求:
    • docker 20.10.10-ce+
    • docker-compose 1.18.0+
  • 注意事项:
    • 数据存放路径应在配置文件中配置到一个容量比较充足的共享存储中
    • Harbor是使用docker-compose命令来管理的,如果需要停止Harbor也应用docker-compose stop来停止
  • 部署docker教程:https://blog.csdn.net/qq_37344058/article/details/131270071
  • 部署docker-compose教程:https://blog.csdn.net/qq_37344058/article/details/136065167
  • 下载地址:https://github.com/goharbor/harbor/releases
    • 需要下载offline的压缩包
      在这里插入图片描述
# 1.下载harbor安装包
wget https://github.com/goharbor/harbor/releases/download/v2.9.3/harbor-offline-installer-v2.9.3.tgz

# 2.解压到/usr/local,并进入到解压目录
tar zxvf harbor-offline-installer-v2.9.3.tgz -C /usr/local/ && cd /usr/local/harbor/

# 3.拷贝一份配置文件
cp harbor.yml.tmpl harbor.yml

# 4.查看当前主机全称
hostname

# 5.修改配置文件
vi harbor.yml
# 5.1 修改hostname
# 5.2 https这行及子行都注释掉,因为没有弄ssl证书加密
  • 下面hostname尽量填IP地址,填hostname有问题
    在这里插入图片描述
# 6.启动harbor
./install.sh

在这里插入图片描述
注意:这是因为在启动docker的时候防火墙做了策略,如果容器在运行中,停止防火墙,在操作容器就会报这个错误,我们可以重启docker解决此问题
重启docker服务:systemctl restart docker.service
启动harbor:docker-compose up -d

  • Harbor的命令汇总
    • 启动harbor:docker-compose up -d
    • 关闭harbor:docker-compose stop
    • 重启harbor:docker-compose restart

2.访问

访问地址:harbor的服务器ip地址
账号密码:用户名(admin)、密码(可在harbor.yml配置文件中找到,修改密码的话也在这里面改)

3.创建项目

  • Harbor的项目分为公开和私有的
    • 公开项目:所有用户都可以访问,通常存放公共的镜像,默认有一个library公开项目。
    • 私有项目:只有授权用户才可以访问,通常存放项目本身的镜像。
  • 以下为微服务创建一个项目
    在这里插入图片描述
    在这里插入图片描述
  • 创建了个私有项目

4.创建用户

在这里插入图片描述

5.给用户分配项目

  • 分配项目的时候,可以选择角色:
    • 项目管理员:对当前项目有所有权限
    • 维护人员:拥有对 Harbor 系统的维护权限,包括监控系统状态、执行备份和恢复操作、维护存储等。
    • 开发人员:对镜像进行上传和下载
    • 访客:只能下载,不能上传
      在这里插入图片描述

6.本地镜像上传

  • 上传刚刚创建的eureka镜像

6.1 给镜像打上标签

# 通用格式:docker tag 镜像名称:镜像版本 harbor的IP:85/项目名称/镜像名称:镜像版本
docker tag eureka:v1 192.168.86.128/tensquare/eureka:v1

6.2 将harbor地址添加到Docker白名单

  • 默认情况,docker不允许把镜像传入到harbor,因为docker不新人harbor地址

vi /etc/docker/daemon.json

{
    "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"],
    "insecure-registries": ["192.168.86.128"]
}

重启docker:systemctl restart docker
启动harbor:cd /usr/local/harbor && docker-compose up -d

6.3 命令行登录harbor

docker login -u 用户名 -p 密码 192.168.86.128

6.4 推送镜像

docker push 192.168.86.128/tensquare/eureka:v1

在这里插入图片描述

6.5 从Harbor下载镜像

6.5.1 命令行登录Harbor
docker login -u 用户名 -p 密码 192.168.86.128
6.5.2 拉取镜像
docker pull 192.168.86.128/tensquare/eureka:v1

七、微服务持续集成-案例

1.项目上传到gitlab

1.1 创建git项目

  • 需要创建两个项目:
    • 前端:tensquare_front
    • 后端:tensquare_back
      在这里插入图片描述

1.2 IDEA上传后端项目

1.2.1 配置git程序

在这里插入图片描述

1.2.2 配置GitLab

在这里插入图片描述

  • 将ssh的链接,填入进去即可。
1.2.3 上传代码

在这里插入图片描述
在这里插入图片描述

1.3 Git上传前端代码

  • 步骤
    • 将前端仓库clone
    • 将前端代码粘贴进去
    • 提交后push
# 1.将前端仓库clone
git clone ssh://git@192.168.86.128:9922/tensquare/tensquare_front.git
cd tensquare_front
# 2.创建分支
git switch --create main
# 3.提交代码
git add . && git commit -m "初始化项目" && git push --set-upstream origin main

在这里插入图片描述

2.在Jenkins从GitLab拉取源码

2.1 创建Jenkins微服务项目

  • 创建两个微服务项目,并且都是流水线项目
    • 前端:tensquare_front
    • 后端:tensquare_back
2.1.1 创建后端Jenkins项目

在这里插入图片描述
在这里插入图片描述

2.1.2 编写Jenkins脚本文件
  • 脚本文件放到父工程根根目录:Jenkinsfile
  • 下面是脚本式
  • 检出git脚本生成
    在这里插入图片描述
checkout scmGit(branches: [[name: '*/master']], extensions: [], userRemoteConfigs: [[credentialsId: '6856b58c-2349-4673-aec6-278f08335aff', url: 'http://192.168.86.128:9980/tensquare/tensquare_back.git']])
  • 将一些变量抽取出来
//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"

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

在这里插入图片描述

2.1.3 编写每个微服务harbor配置
  • 在每一个微服务下面,防止一个harbor代码扫描的配置文件:sonar-project.properties
2.1.3.1 zuul
# 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
2.1.3.2 eureka
# 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
2.1.3.3 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
2.1.3.3 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
2.1.4 流水线添加harbor
  • 由于涉及到多个微服务,构建的时候,需要有个下拉框可以选择,构建哪些微服务。以下是添加微服务名称下拉框,可以多选
    在这里插入图片描述
  • 下面是加入了代码扫描的pipeline代码
//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"

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

3.微服务打包

3.1 Jenkins环境准备

3.1.1 安装项目java环境
3.1.2 安装maven环境
  • 安装教程:https://qingsi.blog.csdn.net/article/details/137710489
  • maven环境如果安装了,运行jenkins报错
    在这里插入图片描述
  • 因为Jenkins 通过shell脚本调用 mvn 命令的时候,是从/usr/bin 文件夹中找命令的
ln -s /usr/local/maven/apache-maven-3.6.3/bin/mvn /usr/bin/mvn
ln -s /usr/local/maven/apache-maven-3.6.3/bin/mvn /usr/local/bin/mvn
3.1.3 将父工程依赖文件放入maven环境
  • 第一种方案:资料包里面有:tensquare_parent.tar.gz
    • 放入到:/data/mavenfile/com/tensquare下面
  • 第二种方案:打包安装父工程:mvn -f pom.xml clean install
    • pom.xml是父工程的
3.1.4 docker环境
  • 需要安装docker环境

3.2 对公共子工程打包

  • 由于公共子工程不是Spring服务启动的,而其他的服务依赖于这个包,所以需要提前将公共子工程打包好,并且安装到maven本地仓库
  • 在Jenkinsfile加入打包子工程打包安装的步骤
//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"

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

3.3 对微服务打包

  • 在Jenkinsfile加入新步骤打包微服务
//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"

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

4.使用Dockerfile编译、生成镜像

4.1 配置构建docker的插件

  • 在每个微服务项目的pom.xml加入dockerfile-maven-plugin插件
<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>

4.2 配置Dockerfile

  • 在每个微服务项目根目录下建立Dockerfile文件
  • 注意:每个项目公开的端口不一样
#FROM java:8
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 9002
ENTRYPOINT ["java","-jar","/app.jar"]
  • 在父工程的Jenkinsfile添加docker build的命令
//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"

node {
   stage('拉取代码') {
       checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])
   }
   stage('代码审查') {
       //定义当前Jenkins的SonarQubeScanner工具:下面配置的是 全局配置里面的name
       def scannerHome = tool 'sonar-scanner'
       //引用当前JenkinsSonarQube环境:下面配置的是系统配置的name
       withSonarQubeEnv('SonarQube-Server') {
            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"
        }
}

在这里插入图片描述

5.上传到Harbor镜像库

  • 修改Jenkinsfile脚本
//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"
//镜像的版本号
def tag = "latest"
//Harbor的url地址
def harbor_url = "192.168.86.128"
//镜像库项目名称
def harbor_project = "tensquare"
//Harbor的登录凭证ID:这个ID,是在jenkins里面创建的凭证(harbor的账号密码)的ID
def harbor_auth = "bf8ca22e-aee0-4533-bf63-185dac0bef1a"

node {
   stage('拉取代码') {
       checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])
   }
   stage('代码审查') {
       //定义当前Jenkins的SonarQubeScanner工具:下面配置的是 全局配置里面的name
       def scannerHome = tool 'sonar-scanner'
       //引用当前JenkinsSonarQube环境:下面配置的是系统配置的name
       withSonarQubeEnv('SonarQube-Server') {
            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打包发布成功
    在这里插入图片描述
  • harbor显示有镜像保存
    在这里插入图片描述

6.拉取镜像和发布应用

  • 本次案例,在jenkins的服务器(192.168.86.128)上面,发布到应用服务器(192.168.86.131)上面部署。和部署到其他服务器一样的步骤。
  • 部署应用的机器环境:
    • 确保安装了docker

6.1 Jenkins安装发布插件

  • Publish Over SSH插件
    在这里插入图片描述

6.2 ssh公钥配置

6.2.1 公钥传输
  • 查看jenkins的机器上是否有密钥公钥:
    • 查看/root/.ssh 是否有:id_rsa.pub、id_rsa文件
      在这里插入图片描述
  • 如果没有的话,需要生成:
ssh-keygen -t rsa -C 'xxx@xxx.com'
# 下面一路回车即可
  • 将jenkins服务器的公钥,传送到应用部署的服务器上
ssh-copy-id 192.168.86.128

在这里插入图片描述

6.2.2 jenkins公钥配置

在这里插入图片描述

  • Passphrase:是填写jenkins服务器生成的ssh key的密码,一般置空,不予理睬
  • path to key:jenkins服务器生成的私钥存放目录文件。
  • key:直接填写jenkins服务器生成的私钥。
  • 注意:path to key 和 key 二选一即可
6.2.2 jenkins项目构建添加端口参数
  • 这个参数用于传入到启动微服务容器的端口
    在这里插入图片描述
    在这里插入图片描述
6.2.3 Jenkinsfile添加部署命令
  • 可以在流水线代码生成那里生成命令
    在这里插入图片描述
//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"
//镜像的版本号
def tag = "latest"
//Harbor的url地址
def harbor_url = "192.168.86.128"
//镜像库项目名称
def harbor_project = "tensquare"
//Harbor的登录凭证ID:这个ID,是在jenkins里面创建的凭证(harbor的账号密码)的ID
def harbor_auth = "bf8ca22e-aee0-4533-bf63-185dac0bef1a"

node {
   stage('拉取代码') {
       checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])
   }
   stage('代码审查') {
       //定义当前Jenkins的SonarQubeScanner工具:下面配置的是 全局配置里面的name
       def scannerHome = tool 'sonar-scanner'
       //引用当前JenkinsSonarQube环境:下面配置的是系统配置的name
       withSonarQubeEnv('SonarQube-Server') {
            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}"

               def i = "docker push ${harbor_url}/${harbor_project}/${imageName}"
               sh "echo ${i}"

               sh "echo 镜像上传成功"
           }

           // 部署应用
           // 1.execCommand的$port,需要作为一个构建参数传入
           sh "echo 开始部署"
           def execCommand = "/opt/jenkins_shell/deploy.sh ${harbor_url} ${harbor_project} ${project_name} ${tag} ${port}"
           sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${execCommand}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
           sh "echo 部署完成"
        }
}
6.2.3 编写sh部署脚本
  • 该放置到部署应用服务器,路径为:/opt/jenkins_shell
  • 脚本名称:deploy.sh
  • 注意:脚本需要授权:chmod +x de
#! /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 "容器启动成功"

6.3 导入微服务的表和数据

  • tensquare_gathering.sql、tensquare_user.sql

6.4 修改所有微服务注册中心配置地址

  • 将注册中心的地址,改为实际部署的服务器地址

6.4 按顺序构建docker并自动部署

  • 微服务构建顺序:
    • tensquare_eureka_server
    • tensquare_zuul
    • tensquare_admin_service
    • tensquare_gathering
      在这里插入图片描述

6.5 测试接口

  • 登录接口
    在这里插入图片描述

7.部署前端静态web网站

在这里插入图片描述

7.1 部署服务器安装nginx

  • Docker部署nginx教程:https://blog.csdn.net/qq_37344058/article/details/137742556

7.2 Jenkins配置NodeJS

7.2.1 安装NodeJS插件
  • 安装插件NodeJS
    在这里插入图片描述
7.2.2 安装NodeJS版本

在这里插入图片描述

7.3 创建前端流水线

  • 项目名称:tensquare_front
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
// gitlab的凭证
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"

node {
   stage('拉取代码') {
       checkout scmGit(branches: [[name: '*/${branch}']], extensions: [], userRemoteConfigs: [[credentialsId: '${git_auth}', url: 'http://192.168.86.128:9980/tensquare/tensquare_front.git']])
   }
   stage('代码审查') {
       // 使用NodeJS的npm进行打包
       nodejs("nodejs12"){
        sh '''
            npm install
            npm run build
        '''

        // 以下为远程调用进行项目部署:使用的是目录拷贝的方式
        sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '/root/docker/nginx/html', remoteDirectorySDF: false, removePrefix: 'dist', sourceFiles: 'dist/**')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])

       }
   }
}

7.4 修改前端文件BASE_API地址

  • 修改为网关地址
    在这里插入图片描述

7.5 Jenkins构建

在这里插入图片描述

八、微服务持续集成-优化

1.存在的问题

  • 上面部署方案存在的问题:
    • 一次只能选择一个微服务部署
    • 只有一台生产者部署服务器
    • 每个微服务只有一个实例,容错率低
  • 优化方案:
    • 在一个Jenkins工程中可以选择多个微服务同时发布
    • 在一个Jenkins工程中可以选择多台生产服务器同时部署
    • 每个微服务都是以集群高可用形式部署
      在这里插入图片描述

2.集群版eureka配置

2.1 eureka微服务配置文件

  • 在启动微服务的时候,加入参数: spring.profiles.active 来读取对应的配置
# 集群版
spring:
  application:
    name: EUREKA-HA

---
server:
  port: 10086
spring:
  # 指定profile=eureka-server1
  profiles: eureka-server1
eureka:
  instance:
    # 指定当profile=eureka-server1时,主机名是eureka-server1
    hostname: 192.168.86.131
  client:
    service-url:
      # 将自己注册到eureka-server1、eureka-server2这个Eureka上面去
      defaultZone: http://192.168.86.131:10086/eureka/,http://192.168.86.132:10086/eureka/

---
server:
  port: 10086
spring:
  profiles: eureka-server2
eureka:
  instance:
    hostname: 192.168.86.132
  client:
    service-url:
      defaultZone: http://192.168.86.131:10086/eureka/,http://192.168.86.132:10086/eureka/

2.2 其他微服务配置文件

  • 将defaultZone改为:http://192.168.86.131:10086/eureka/,http://192.168.86.132:10086/eureka
    在这里插入图片描述

2.3 Jenkins多选类型参数

2.3.1 安装多选框组件
  • Extended Choice Parameter Plugin
    在这里插入图片描述
2.3.2 创建流水线项目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.3.3 添加微服务项目多选参数

在这里插入图片描述
在这里插入图片描述

2.3.4 添加部署服务器多选参数

在这里插入图片描述

2.4 Jenkinsfile编写

//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"
//镜像的版本号
def tag = "latest"
//Harbor的url地址
def harbor_url = "192.168.86.128"
//镜像库项目名称
def harbor_project = "tensquare"
//Harbor的登录凭证ID:这个ID,是在jenkins里面创建的凭证(harbor的账号密码)的ID
def harbor_auth = "bf8ca22e-aee0-4533-bf63-185dac0bef1a"

node {
   // 获取当前选择的项目名称
   def selectedProjectNames = "${project_name}".split(",")
  //获取当前选择的服务器名称
  def selectedServers = "${publish_server}".split(",")
   stage('拉取代码') {
       checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])
   }
   stage('代码审查') {
       // for循环每个项目代码
       for(int i=0;i<selectedProjectNames.length;i++){
              // tensquare_eureka_server@10086
              def projectInfo = selectedProjectNames[i];
              // 当前遍历的项目名称
              def currentProjectName = "${projectInfo}".split("@")[0]
              // 当前遍历的项目端口
              def currentProjectPort = "${projectInfo}".split("@")[1]
              //定义当前Jenkins的SonarQubeScanner工具:下面配置的是 全局配置里面的name
              def scannerHome = tool 'sonar-scanner'
              //引用当前JenkinsSonarQube环境:下面配置的是系统配置的name
              withSonarQubeEnv('SonarQube-Server') {
                   sh """
                           cd ${currentProjectName}
                           ${scannerHome}/bin/sonar-scanner
                   """
              }
       }

   }
   stage('编译,安装公共子工程') {
         sh "mvn -f tensquare_common clean install"
      }
  stage('编译,打包微服务工程,上传镜像') {
         // for循环每个项目代码
         for(int i=0;i<selectedProjectNames.length;i++){
                // tensquare_eureka_server@10086
                def projectInfo = selectedProjectNames[i];
                // 当前遍历的项目名称
                def currentProjectName = "${projectInfo}".split("@")[0]
                // 当前遍历的项目端口
                def currentProjectPort = "${projectInfo}".split("@")[1]
                sh "mvn -f ${project_name} clean package dockerfile:build"

               //定义镜像名称
               def imageName = "${currentProjectName}:${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}"

                   def i = "docker push ${harbor_url}/${harbor_project}/${imageName}"
                   sh "echo ${i}"

                   sh "echo 镜像上传成功"
               }

               // 遍历所有的服务器,分别部署
                for(int j=0;j<selectedServers.length;j++){
                       //获取当前遍历的服务器名称
                       def currentServerName = selectedServers[j]

                       //加上的参数格式:--spring.profiles.active=eureka-server1/eureka-server2
                       def activeProfile = "--spring.profiles.active="
                       //根据不同的服务名称来读取不同的Eureka配置信息
                       if(currentServerName=="master_server"){
                          activeProfile = activeProfile+"eureka-server1"
                       }else if(currentServerName=="slave_server"){
                          activeProfile = activeProfile+"eureka-server2"
                       }
                      // 部署应用
                      def execCommand = "/opt/jenkins_shell/deployCluster.sh ${harbor_url} ${harbor_project} ${currentProjectName} ${tag} ${currentProjectPort} ${activeProfile}"
                      sshPublisher(publishers: [sshPublisherDesc(configName: "${currentServerName}", transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${execCommand}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
                }
         }
     }
}

2.5 部署sh脚本编写

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

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 eric -p Eric123456 $harbor_url

# 下载镜像
docker pull $imageName

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

echo "容器启动成功"

八、Nginx+zuul集群实现高可用网关

  • 这里只需要使用nginx的负载均衡功能即可
    在这里插入图片描述

1.安装nginx

  • 之前已经安装过

2.修改nginx配置

vi /etc/nginx/nginx.conf

加入以下内容

    upstream zuulServer {
		server 192.168.66.103:10020 weight=1;
		server 192.168.66.104:10020 weight=1;
	}
server {
	location / {
		proxy_pass http://zuulServer/;
	}
}

3.重启nginx

  • 由于是docker部署的:docker restart nginx

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/544364.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

陇剑杯 ios 流量分析

陇剑杯 ios 流量分析 ios 一位ios的安全研究员在家中使用手机联网被黑&#xff0c;不仅被窃密还丢失比特币若干&#xff0c;根据流量分析完成ios1-8 ios 1 ios-1&#xff1a;黑客所控制的C&C服务器IP是_____________。 什么是C&C服务器? C&C&#xff08;Com…

回溯算法中常见的使用方法逻辑整理

回溯算法 常见的使用方法逻辑整理 1. 回溯算法 特点 回溯算法实际上一个类似枚举的搜索尝试过程&#xff0c;主要是在搜索尝试过程中寻找问题的解&#xff0c;当发现已不满足求解条件时&#xff0c;就“回溯”返回&#xff0c;尝试别的路径。回溯法是一种选优搜索法&#xff0…

乐写9612手写板实测故障

闲鱼上淘了二手的 ①需要驱动很强的usb口&#xff0c;老usb口会不识别&#xff0c;尤其是笔记本容易不识别&#xff0c;非常容易出现下面这种问题&#xff1a; ②需要microsoft2013以上的&#xff0c;兼容性做的比较差 ③由于可视化&#xff0c;导致数据线容易烧&#xff0c;…

stm32报错问题集锦

PS&#xff1a;本文负责记录本人日常遇到的报错问题&#xff0c;以及问题描述、原因以及解决办法等&#xff0c;解决办法百分百亲测有效。本篇会不定期更新&#xff0c;更新频率就看遇到的问题多不多了 更换工程芯片型号 问题描述 例程最开始用的芯片型号是STM32F103VE&#…

CentOS 7安装Nginx

说明&#xff1a;本文介绍如何在CentOS 7操作系统中安装Nginx 下载安装 首先&#xff0c;去官网上下载Nginx压缩包&#xff0c;官网地址&#xff1a;https://nginx.org/en/download.html&#xff0c;我这里下载稳定版1.24.0&#xff1b; 上传到云服务器上&#xff0c;解压&am…

数据可视化基础与应用-04-seaborn库人口普查分析--如何做人口年龄层结构金字塔

总结 本系列是数据可视化基础与应用的第04篇seaborn&#xff0c;是seaborn从入门到精通系列第3篇。本系列主要介绍基于seaborn实现数据可视化。 参考 参考:我分享了一个项目给你《seaborn篇人口普查分析–如何做人口年龄层结构金字塔》&#xff0c;快来看看吧 数据集地址 h…

【题目】【信息安全管理与评估】2022年国赛高职组“信息安全管理与评估”赛项样题5

【题目】【信息安全管理与评估】2022年国赛高职组“信息安全管理与评估”赛项样题5 第一阶段竞赛项目试题 本文件为信息安全管理与评估项目竞赛-第一阶段试题&#xff0c;第一阶段内容包括&#xff1a;网络平台搭建与设备安全防护。 本次比赛时间为180分钟。 介绍 竞赛阶段…

Unity 人形骨骼动画模型嘴巴张开

最近搞Daz3D玩&#xff0c;导入后挂上动画模型嘴巴张开&#xff0c;其丑无比。 Google了一下&#xff0c;得知原因是Unity没有对下巴那根骨骼做控制&#xff0c;动画系统就会把它放到默认的位置&#xff0c;嘴巴就张开了。找到了3种解决办法。 1.移除动画中对下巴这个骨骼的转…

简单认识Git(dirsearch、githack下载),git泄露(ctfhub)

目录 dirsearch下载地址: githack下载&#xff08;一次不成功可多试几次&#xff09; 一、什么是Git 1.git结构 2.git常用命令及示例 3.Git泄露原理 二、Git泄露 1.Log 2.Stash 3.Index 工具准备&#xff1a;dirsearch、githack dirsearch下载地址: GitHub - mauroso…

数据库SQL语言实战(二)

目录 检索查询 题目一 题目二 题目三 题目四 题目五 题目六 题目七 题目八 题目九&#xff08;本篇最难的题目&#xff09; 分析 实现&#xff08;两种方式&#xff09; 模板 总结 检索查询 按照要求查找数据库中的数据 题目一 找出没有选修任何课程的学…

02 MySQL 之 DQL专题

3. 数据库中仅有月薪字段&#xff08;month_salary&#xff09;&#xff0c;要求查询所有员工的年薪&#xff0c;并以年薪(year_salary)输出&#xff1a; 分析&#xff1a; 查询操作中&#xff0c;字段可以参与数学运算as 起别名&#xff0c;但实际上可以省略 #以下两句效果…

深入了解数据结构第四弹——排序(1)——插入排序和希尔排序

前言&#xff1a; 从本篇开始&#xff0c;我们就开始进入排序的学习&#xff0c;在结束完二叉树的学习之后&#xff0c;相信我们对数据在内存中的存储结构有了新的认识&#xff0c;今天开始&#xff0c;我们将进入排序的学习&#xff0c;今天来学习第一篇——插入排序 目录 什…

使用DockerCompose安装Redis

本文使用docker-compose的方式安装Redis&#xff0c;如何未安装docker-compose&#xff0c;可以参考这篇文章进行安装【在Ubuntu上安装Docker Compose】 一、创建一个DockerCompose配置文件 第一步&#xff1a;创建相关目录文件 为了更好的组织管理Docker容器的配置文件和映射…

毕业后个人档案如何查询

毕业后个人档案查询通常需要在所在学校的学籍管理部门或学生事务处进行查询。具体步骤如下&#xff1a; 1. 准备相关材料&#xff1a;身份证或护照复印件&#xff0c;毕业证书复印件&#xff0c;学号等相关信息。 2. 前往学校学籍管理部门或学生事务处&#xff0c;咨询个人档案…

C语言中局部变量和全局变量是否可以重名?为什么?

可以重名 在C语言中, 局部变量指的是定义在函数内的变量, 全局变量指的是定义在函数外的变量 他们在程序中的使用方法是不同的, 当重名时, 局部变量在其所在的作用域内具有更高的优先级, 会覆盖或者说隐藏同名的全局变量 具体来说: 局部变量的生命周期只在函数内部,如果出了…

专业140+总分410+北京理工大学826信号处理导论考研经验北理工电子信息通信工程,真题,参考书,大纲。

今年考研专业课826信号处理导论&#xff08;信号系统和数字信号处理&#xff09;140&#xff0c;总分410&#xff0c;顺利上岸&#xff01;回看去年将近一年的复习&#xff0c;还是记忆犹新&#xff0c;有不少经历想和大家分享&#xff0c;有得有失&#xff0c;希望可以对大家复…

[管理者与领导者-163] :团队管理 - 高效执行力 -1- 高效沟通的架构、关键问题、注意事项

目录 前言&#xff1a;沟通是管理者实施管理最重要的工作 一、人与人沟通模型 1.1 模型 1.2 完整过程 1.3 发送和接受方式 1.4 传输 1.5 关于编码与解码 1.6 反馈 1.7 沟通中常见问题 二、管理者如何提高沟通的效率 2.1 为什么管理者布置任务后&#xff0c;总有人…

HarmonyOS实战开发-状态管理、通过使用页面级的状态变量 和应用级的状态变量 来实现应用的状态管理。

介绍 本示例通过使用页面级的状态变量 和应用级的状态变量 来实现应用的状态管理。 效果预览 使用说明 1.点击首页中的基本类型进入对应页面&#xff0c;点击按钮可以更改圆形的颜色&#xff1b;点击查看源码可以展示基本类型功能效果的源码。 2.点击首页中的数组类型进入对…

微信小程序实现预约生成二维码

业务需求&#xff1a;点击预约按钮即可生成二维码凭码入校参观~ 一.创建页面 如下是博主自己写的wxml&#xff1a; <swiper indicator-dots indicator-color"white" indicator-active-color"blue" autoplay interval"2000" circular > &…

为什么光伏探勘测绘需要无人机?

随着全球对可再生能源需求的不断增长&#xff0c;光伏产业也迎来了快速发展的机遇。光伏电站作为太阳能发电的主要形式之一&#xff0c;其建设前期的探勘测绘工作至关重要。在这一过程中&#xff0c;无人机技术的应用正逐渐展现出其独特的优势。那么&#xff0c;为什么光伏探勘…