五、Jenkins、Docker、SpringClound持续集成

news2024/11/17 9:45:36

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Tomcat源码解析——Tomcat的启动流程

一、启动脚本 当我们在服务启动Tomcat时&#xff0c;都是通过执行startup.sh脚本启动。 在Tomcat的启动脚本startup.sh中&#xff0c;最终会去执行catalina.sh脚本&#xff0c;传递的参数是start。 在catalina.sh脚本中&#xff0c;前面是环境判断和初始化参数&#xff0c;最终…

架构师系列-搜索引擎ElasticSearch(六)- 映射

映射配置 在创建索引时&#xff0c;可以预先定义字段的类型&#xff08;映射类型&#xff09;及相关属性。 数据库建表的时候&#xff0c;我们DDL依据一般都会指定每个字段的存储类型&#xff0c;例如&#xff1a;varchar、int、datetime等&#xff0c;目的很明确&#xff0c;就…

45.HarmonyOS鸿蒙系统 App(ArkUI)创建列表(List)

列表是一种复杂的容器&#xff0c;当列表项达到一定数量&#xff0c;内容超过屏幕大小时&#xff0c;可以自动提供滚动功能。它适合用于呈现同类数据类型或数据类型集&#xff0c;例如图片和文本。在列表中显示数据集合是许多应用程序中的常见要求&#xff08;如通讯录、音乐列…

Qt快速入门(MV架构之TableView + QStandardItemModel + 自定义代理小案例)

Qt快速入门&#xff08;MV架构之TableView QStandardItemModel 自定义代理小案例&#xff09; 关于MV架构的简单介绍 在Qt框架中&#xff0c;代理&#xff08;Delegate&#xff09;、模型&#xff08;Model&#xff09;和视图&#xff08;View&#xff09;之间的关系构成了…

14_SpringMVC

文章目录 MVCSpringMVC与JavaEE对比SpringMVCSpringMVC的核心流程SpringMVC入门案例RequestMapping注解的使用Handler方法的返回值Handler方法的形参keyvalue形式的请求参数Json请求参数 RESTful风格接口静态资源处理FilterHandlerInterceptor异常处理SpringMVC核心流程流程图 …

自动化收集Unity版本更新日志

自动化收集Unity版本更新日志 &#x1f365;功能介绍&#x1f96a;食用手册填写配置开始搜集 &#x1f368;数据展示 &#x1f365;功能介绍 &#x1f4a1;获取指定年份中所有的Unity版本更新日志。 &#x1f4a1;根据指定字符串过滤。 &#x1f4a1;.收集后自动保存成markdow…

架构师系列-搜索引擎ElasticSearch(四)- 高级查询

ES查询 matchAll 脚本方式 该方式可以通过kabana、curl、elasticsearch-head&#xff08;纯前端&#xff09;去操作 # 默认情况下&#xff0c;es一次展示10条数据,通过from和size来控制分页 # 查询结果详解 GET goods/_search {"query": {"match_all":…

如何在MacOS上使用OpenHarmony SDK交叉编译?

本文以cJSON三方库为例介绍如何通过OpenHarmony的SDK在Mac平台进行交叉编译。 环境准备 SDK准备 我们可以通过 openHarmony SDK 官方发布渠道下载对应mac版本的SDK&#xff0c;当前OpenHarmony MAC版本的SDK有2种&#xff0c;一种是x86架构&#xff0c;另一种是arm64&#x…

二叉树例题分享

文章目录 二叉树例题分享[235. 二叉搜索树的最近公共祖先](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/)[701. 二叉搜索树中的插入操作](https://leetcode.cn/problems/insert-into-a-binary-search-tree/)[108. 将有序数组转换为二叉搜索树…

分享一些有趣的 Linux 命令

1、sl 会显示一辆火车穿过你的终端屏幕 2、cmatrix 在终端中显示类似于《黑客帝国》电影中的绿色数字雨效果 3、fortune 显示一个随机的名人名言或者笑话 4、cowsay 让一头牛说出你输入的话 5、toilet 在终端中将输入的文本以艺术字体的形式呈现 6、figlet 类似于 toile…

Python数据分析案例41——基于CNN-BiLSTM的沪深300收盘价预测

案例背景 虽然我自己基于各种循环神经网络做时间序列的预测已经做烂了.....但是还是会有很多刚读研究生或者是别的领域过来的小白来问这些神经网络怎么写&#xff0c;怎么搭建&#xff0c;给我一篇论文看看感觉很厉害的样子。我一看&#xff1a;普刊、单变量时间序列预测、一个…

软考中级工程师网络技术第二节网络体系结构

OSPF将路由器连接的物理网络划分为以下4种类型&#xff0c;以太网属于&#xff08;25&#xff09;&#xff0c;X.25分组交换网属于&#xff08;非广播多址网络NBMA&#xff09;。 A 点对点网络 B 广播多址网络 C 点到多点网络 D 非广播多址网络 试题答案 正确答案&#xff1a; …

VS2019调试

最近开始了解单步调试 开始我按下F11键是没用的。 Visual Studio 调试快捷键失效_visual studio code用不了快捷键-CSDN博客 我的F11对应的系统功能是调小音量。 所以有两种模式&#xff1a; (1)按下F11,调小音量 (2)按下F11,单步调试 通过Fnesc键进行模式的切换。 还有一…

数据结构初阶:二叉树(二)

二叉树链式结构的实现 前置说明 在学习二叉树的基本操作前&#xff0c;需先要创建一棵二叉树&#xff0c;然后才能学习其相关的基本操作。由于现在对二叉树结构掌握还不够深入&#xff0c;为了降低学习成本&#xff0c;此处手动快速创建一棵简单的二叉树&#xff0c;快速进入二…

网络篇10 | 网络层 IP

网络篇10 | 网络层 IP 01 简介02 名称解释03 IP报文格式(IPv4)1&#xff09;4位版本协议(version)2&#xff09;4位首部长度(header length)3&#xff09;8位服务类型(Type Of Service, TOS)4&#xff09;16位总长度5&#xff09;16位(分片)标识6&#xff09;3位(分片)标志7&am…

【算法】回溯:与递归,dfs的同质与分别,剪枝与恢复现场的详细理解,n皇后的回溯解法及算法复杂度分析。

目录 ​编辑 1.什么是回溯 2.关于剪枝 3.关于恢复现场 4.题目&#xff1a;二叉树的所有路径&#xff08;凸显恢复现场&#xff1a;切实感受回溯与深搜&#xff09; 问题分析 ①函数设置为&#xff1a;void Dfs(root) ②函数设置为&#xff1a;void Dfs(root,path) 解题思想&…

unity记一下如何播放动画

我使用的版本是2022.3.14fc 展开你的模型树&#xff0c;是会出现这个三角形的东西的 然后在资源面板创建一个animation controller 进去之后&#xff0c;把三角形拖进去&#xff0c;就会出现一个动画&#xff0c;然后点击他 在左侧给他创建这么个状态名字&#xff0c;类型…

【JavaEE多线程】理解和管理线程生命周期

目录 ThreadThread类的常用构造方法Thread类的常见属性启动一个线程-start()终止一个线程等待一个线程-join()线程的状态 Thread Thread 就是在 Java 中&#xff0c;线程的代言人。系统中的一个线程&#xff0c;就对应到 Java 中的一个 Thread 对象。围绕线程的各种操作&#…

webrtc中的Track,MediaChannel,MediaStream

文章目录 Track,MediaChannel,MediaStream的关系MediaStream的创建流程创建VideoChannel的堆栈创建VideoStream的堆栈 sdp中媒体参数信息的映射sdp中媒体信息参数设置体系参数设置流程参数映射体系 Track,MediaChannel,MediaStream的关系 Audio/Video track&#xff0c;MediaC…

一款酷黑风个人html引导页

一款酷黑风个人html引导页&#xff0c;如果想要修改的话&#xff0c;请在index.html文件修改图片位置在&#xff0c;images文件夹背景音乐在music文件夹手机端在m文件夹 源码下载 一款酷黑风个人html引导页