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

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

  • Jenkins+Docker+SpringCloud持续集成流程说明
    • SpringCloud微服务源码概述
      • 本地运行微服务
      • 本地部署微服务
    • Docker安装和Dockerfile制作微服务镜像
    • Harbor镜像仓库安装及使用
      • 在Harbor创建用户和项目
      • 上传镜像到Harbor
      • 从Harbor下载镜像
  • 微服务持续集成
    • 项目代码上传到Gitlab
    • 从Gitlab拉取项目源码
    • 提交到SonarQube代码审查
    • 微服务打包构建
    • 使用Dockerfile编译生成镜像
    • 上传到Harbor镜像仓库
    • 拉取镜像和发布应用
    • 配置远程部署服务器
      • 编写远程部署脚本
      • 编写Jenkins流水线脚本
    • 部署和测试所有微服务
    • 部署前端静态web网站

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

在这里插入图片描述

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

服务器列表

服务器名称IP地址安装软件硬件配置系统
代码托管服务器192.168.100.240Gitlab-12.9.92核4GCentOS Linux release 7.5.1804
持续集成服务器192.168.100.241Jenkins 2.401.2,JDK 11,JDK 1.8,Maven 3.8.8,Git 1.8.3.1,Docker 20.10.24-ce2核4GCentOS Linux release 7.5.1804
代码审查服务器192.168.100.242mysql 5.7.43,sonarqube 6.7.71核2GCentOS Linux release 7.5.1804
Harbor仓库服务器192.168.100.251Docker 20.10.24-ce,Harbor 1.9.21核2GCentOS Linux release 7.5.1804
生产部署服务器192.168.100.252Docker 20.10.24-ce1核2GCentOS Linux release 7.5.1804

SpringCloud微服务源码概述

项目架构:前后端分离
后端技术栈:SpringBoot+SpringCloud+SpringDataJpa(Spring全家桶)
微服务项目结构:
在这里插入图片描述

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

数据库结构:

  1. tensquare_user:用户认证数据库,存放用户账户数据。对应tensquare_admin_service微服务
  2. tensquare_gathering:活动微服务数据库。对应tensquare_gathering微服务

微服务配置分析:

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

本地运行微服务

本地运行微服务,按顺序逐一启动

运行eureka服务器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
通过浏览器进入localhost:10086
在这里插入图片描述
开启zuul网关
在这里插入图片描述
在这里插入图片描述
开启权限中心
在这里插入图片描述
在这里插入图片描述
开启微服务
在这里插入图片描述
在这里插入图片描述
刷新Eureka页面业务都成功部署
在这里插入图片描述

本地部署微服务

SpringBoot微服务项目打包,必须导入该插件
在pom.xml里添加
在这里插入图片描述

# 在Pom.xml添加<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>

在这里插入图片描述
项目打包
在这里插入图片描述
在这里插入图片描述
打包后在target下产生jar包
在这里插入图片描述
本地运行微服务的jar包

java -jar xxx.jar

查看效果
在这里插入图片描述
在这里插入图片描述

Docker安装和Dockerfile制作微服务镜像

Docker安装

# 卸载旧版本
sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine
# 删除docker的所有镜像和容器
rm -rf /var/lib/docker# 安装基本的依赖包
sudo yum install yum-utils device-mapper-persistent-data lvm2 -y# 设置镜像仓库 Docker yum源
sudo yum-config-manager \--add-repo \http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo# 更新yum软件包索引
sudo yum makecache fast# 列出需要安装的版本列表
yum list docker-ce --showduplicates | sort -r# 安装docker-ce-20.10
yum install docker-ce-20.10.* docker-ce-cli-20.10.* containerd -ymkdir /etc/docker -p
cat > /etc/docker/daemon.json <<EOF
{"registry-mirrors": ["https://k68iw3ol.mirror.aliyuncs.com"]
}
EOF# 开启内核转发,后续报错排查后回来整理的笔记,重要!!!
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1# 重装使配置生效
sysctl -p /etc/sysctl.confsystemctl daemon-reload && systemctl enable --now docker

部分问题总结

安装docker后无法启动的问题排查
之前所有的安装设置daemon文件为daemon.json格式,但在今天设置后发生报错,并且为之后docker添加harbor地址信任后重启docker埋下伏笔,一直找不到原因,无数次修改json文件,问题的最终在于,参考文章:CentOS7 启动docker.service失败,但又无法连接harbor私有仓库。

cat > /etc/docker/daemon.json <<EOF
{"registry-mirrors": ["https://k68iw3ol.mirror.aliyuncs.com","https://docker.mirrors.ustc.edu.cn","http://hub-mirror.c.163.com"],"exec-opts":["native.cgroupdriver=systemd"]
}
EOF

在这里插入图片描述
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设置容器的挂载卷

利用Dockerfile制作一个Eureka注册中心的镜像

# 将eureka的jar包上传至服务器
mkdir /root/eureka
mv tensquare_eureka_server-1.0-SNAPSHOT.jar /root/eureka/cd /root/eureka/
vim DockerfileFROM 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 image ls
REPOSITORY   TAG            IMAGE ID       CREATED         SIZE
eureka       v1             0147238f31a1   5 seconds ago   150MB
openjdk      8-jdk-alpine   a3562aa0b991   4 years ago     105MB# 创建容器验证镜像是否成功
docker run -id --name=eureka -p 10086:10086 eureka:v1# 查看日志
docker logs -f 容器id

构建镜像
在这里插入图片描述
浏览器访问
在这里插入图片描述

Harbor镜像仓库安装及使用

Harbor简介

在这里插入图片描述
Harbor(港口,港湾)是一个用于存储和分发Docker镜像的企业级Registry服务器。
除了Harbor这个私有镜像仓库之外,还有Docker官方提供的Registry。相对Registry,Harbor具有很多优势:

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

Harbor安装

Harbor需要安装在192.168.100.251
参考文章:Harbor prepare脚本分析

# 安装docker
# 参考之前的安装过程# 安装docker-compose
sudo curl -L "https://kgithub.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-composechmod +x /usr/local/bin/docker-compose
docker-compose version# 安装harbor
wget https://ghproxy.com/https://github.com/goharbor/harbor/releases/download/v1.9.2/harbor-offline-installer-v1.9.2.tgzmkdir /opt/harbor
tar xf harbor-offline-installer-v1.9.2.tgz -C /opt# 修改Harbor的配置
vim harbor.yml5 hostname: 192.168.100.251
10   port: 85
27 harbor_admin_password: Harbor12345  # 也可更改harbor默认密码# 产生配置脚本
./prepare
# 安装Harbor
./install.sh# 启动Harbor
docker-compose up -d    # 启动
docker-compose stop     # 停止
docker-compose restart  # 重新启动# 完成安装后,通过192.168.100.251:85进行浏览器访问

在这里插入图片描述
配置Harbor开机随系统启动,服务器重启后默认Harbor无法正常启动,可以使用systemd管理Harbor启停
参考文章:harbor安装并配置https

# 先停止已经启动的harbor
docker-compose -f docker-compose.yml downcat > /usr/lib/systemd/system/harbor.service << 'EOF'
[Unit]
Description=Harbor
After=docker.service systemd-networkd.service systemd-resolved.service
Requires=docker.service
Documentation=https://github.com/goharbor/harbor[Service]
Type=simple
Restart=on-failure
RestartSec=5
Environment=Harbor_Path=/opt/harbor
ExecStart=/usr/local/bin/docker-compose -f ${Harbor_Path}/docker-compose.yml up
ExecStop=/usr/local/bin/docker-compose -f ${Harbor_Path}/docker-compose.yml down[Install]
WantedBy=multi-user.target
EOFsystemctl daemon-reload && systemctl enable harbor --now

在这里插入图片描述

在Harbor创建用户和项目

创建项目

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

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

我们可以为微服务项目创建一个新的项目:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
创建用户
在这里插入图片描述
在这里插入图片描述
给私有项目分配用户
进入tensquare项目->成员
在这里插入图片描述
在这里插入图片描述

角色权限说明
项目管理员除了读写权限,同时拥有用户管理/镜像扫描等管理权限
维护人员对于指定项目拥有读写权限,创建 Webhooks
开发人员对于指定项目拥有读写权限
访客对于指定项目拥有只读权限

上传镜像到Harbor

# 把Harbor地址加入到Docker信任列表
vim /etc/docker/daemon.json
{"registry-mirrors": ["https://k68iw3ol.mirror.aliyuncs.com"],"insecure-registries": ["192.168.100.251:85"]
}systemctl daemon-reload && systemctl restart docker# 登录Harbor
docker login -u haibo -p LIUhaibo123 192.168.100.251:85# 给镜像打上标签
[root@jenkins eureka]# docker images
REPOSITORY   TAG            IMAGE ID       CREATED          SIZE
eureka       v1             0147238f31a1   36 minutes ago   150MB
openjdk      8-jdk-alpine   a3562aa0b991   4 years ago      105MBdocker tag eureka:v1 192.168.100.251:85/tensquare/eureka:v1[root@jenkins eureka]# docker images
REPOSITORY                            TAG            IMAGE ID       CREATED          SIZE
192.168.100.251:85/tensquare/eureka   v1             0147238f31a1   37 minutes ago   150MB
eureka                                v1             0147238f31a1   37 minutes ago   150MB
openjdk                               8-jdk-alpine   a3562aa0b991   4 years ago      105MB# 推送镜像
docker push 192.168.100.251:85/tensquare/eureka:v1

此时Harbor仓库有了上传的镜像
在这里插入图片描述

从Harbor下载镜像

需求:在192.168.100.252服务器(生产部署服务器)完成从192.168.100.251(Harbor镜像仓库)下载镜像

# 安装Docker,并启动Docker(已完成)# 修改Docker配置添加对Harbor镜像仓库的信任
vim /etc/docker/daemon.json
{"registry-mirrors": ["https://k68iw3ol.mirror.aliyuncs.com"],"insecure-registries": ["192.168.100.251:85"]
}systemctl daemon-reload && systemctl restart docker# 先登录,再从Harbor下载镜像
docker login -u haibo -p LIUhaibo123 192.168.100.251:85
docker pull 192.168.100.251:85/tensquare/eureka:v1docker images

在这里插入图片描述

微服务持续集成

项目代码上传到Gitlab

参考之前的步骤,上传后台微服务和前端web网站代码。

上传后端代码

创建tensquare项目组
在这里插入图片描述
将张三加入项目组,并赋予owner权限
在这里插入图片描述
创建项目
在这里插入图片描述
在这里插入图片描述
此时tensquare组里就有新建的两个项目
在这里插入图片描述
上传代码,通过IDEA操作

首先上传后端微服务代码
启用版本控制集成
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
新建一个仓库地址
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
提交代码到仓库
在这里插入图片描述
在这里插入图片描述
项目成功提交
在这里插入图片描述
上传前端代码

通过Tortoisegit上传
Git小乌龟的安装及使用

在代码目录下右键创建本地仓库
在这里插入图片描述
在这里插入图片描述
提交代码到本地仓库,右键提交–>master
在这里插入图片描述
在这里插入图片描述
管理远程地址
在这里插入图片描述
在这里插入图片描述
使用用户zhangsan执行代码推送
在这里插入图片描述
在这里插入图片描述
前往Gitlab代码仓库查看
在这里插入图片描述
至此,所有代码上传完毕!

从Gitlab拉取项目源码

Jenkins创建后端流水线项目
在这里插入图片描述
添加参数化构建
在这里插入图片描述
添加字符参数
在这里插入图片描述
在这里插入图片描述
配置从版本控制里抓取pipeline脚本
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
使用流水线语法生成流水线脚本
在这里插入图片描述
在这里插入图片描述

// 定义变量以及引用变量,这样维护性好一点
// 引用凭证ID最好使用双引号 ""// git凭证ID
def git_auth = "a4d0066f-6c58-4ab0-b714-6a24b3f5bc90"
// git的URL地址
def git_url = "git@192.168.100.240:tensquare_group/tensquare_back.git"node {stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}
}

上传Jenkinsfile文件至仓库,以便Jenkins项目能够获取脚本文件执行项目构建
在这里插入图片描述
在这里插入图片描述
进入代码仓库查看
在这里插入图片描述
开始构建项目,默认使用master分支
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

提交到SonarQube代码审查

进入tensquare_back项目,添加两个参数
在参数化构建过程添加(Choice Parameter)
在这里插入图片描述
添加需要选择审查的项目名称
在这里插入图片描述
点击构建查看效果
在这里插入图片描述
项目的根目录下添加sonar-project.properties
首先在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,注意:修改sonar.projectKeysonar.projectName
修改Jenkinsfile

// git凭证ID
def git_auth = "a4d0066f-6c58-4ab0-b714-6a24b3f5bc90"
// git的URL地址
def git_url = "git@192.168.100.240:tensquare_group/tensquare_back.git"node {stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}stage('代码审查') {// 定义当前Jenkins的SonarQubeScanner工具的环境,位于全局工具配置的SonarQube Scanner 的name定义为'sonar-scanner'def scannerHome = tool 'sonar-scanner'// 引用当前JenkinsSonarQube的环境,系统配置的SonarQube servers定义的name以及代码审查服务器位置withSonarQubeEnv('sonarqube') {sh """cd ${project_name}${scannerHome}/bin/sonar-scanner"""}}
}

由于修改了很多文件,统一提交至仓库
在这里插入图片描述
构建项目并测试代码审查能否完成
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
sonarqube后台查看审查结果
在这里插入图片描述
将其他三个项目也做代码审查
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

微服务打包构建

编译构建之前需要对一个公共子工程编译安装

//Jenkinsfile文件添加步骤// git凭证ID
def git_auth = "a4d0066f-6c58-4ab0-b714-6a24b3f5bc90"
// git的URL地址
def git_url = "git@192.168.100.240:tensquare_group/tensquare_back.git"node {stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}stage('代码审查') {// 定义当前Jenkins的SonarQubeScanner工具的环境,位于全局工具配置的SonarQube Scanner 的name定义为'sonar-scanner'def scannerHome = tool 'sonar-scanner'// 引用当前JenkinsSonarQube的环境,系统配置的SonarQube servers定义的name以及代码审查服务器位置withSonarQubeEnv('sonarqube') {sh """cd ${project_name}${scannerHome}/bin/sonar-scanner"""}}stage('编译安装公共子工程') {sh "mvn -f tensquare_common clean install"}
}

Jenkinsfile文件上传至代码仓库,再尝试构建
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
构建失败
在这里插入图片描述
如果编译构建失败,进入IDEA
tensquare_parent父工程里面的spring-boot-maven插件移到需要项目打包的项目里去

tensquare_common子工程不需要这个插件
只需要将插件加入tensquare_eureka_servertensquare_admin_servicetensquare_gatheringtensquare_zuul

    <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build><!-- 在project里添加 -->
</project>

调整好之后,上传至Gitlab代码服务器
再次尝试对公共子工程进行打包,此时可以看到公共子工程安装到了本地maven仓库
在这里插入图片描述
在这里插入图片描述
继续编写Jenkinsfile,需要对其他微服务进行打包

// git凭证ID
def git_auth = "a4d0066f-6c58-4ab0-b714-6a24b3f5bc90"
// git的URL地址
def git_url = "git@192.168.100.240:tensquare_group/tensquare_back.git"node {stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}stage('代码审查') {// 定义当前Jenkins的SonarQubeScanner工具的环境,位于全局工具配置的SonarQube Scanner 的name定义为'sonar-scanner'def scannerHome = tool 'sonar-scanner'// 引用当前JenkinsSonarQube的环境,系统配置的SonarQube servers定义的name以及代码审查服务器位置withSonarQubeEnv('sonarqube') {sh """cd ${project_name}${scannerHome}/bin/sonar-scanner"""}}stage('编译安装公共子工程') {sh "mvn -f tensquare_common clean install"}stage('编译打包微服务工程') {// 项目参数传入的project_name 修改为变量sh "mvn -f ${project_name} clean package"}
}

首先对eureka服务器进行打包
在这里插入图片描述
在这里插入图片描述
来到Jenkins工作目录下查看一下
tensquare_eureka_server进行了打包并且target下有jar包
在这里插入图片描述
将其它三个微服务以同样方式打包

但打包tensquare_zuul报错
在这里插入图片描述
网关依赖父工程,但仓库里的父工程没有
因此需要按照父工程的目录结构将父工程pom.xml文件上传到Jenkins服务器的maven仓库,对应的maven仓库里去以便构建时网关服务找到父工程
那么这个动作需要手动完成

[root@jenkins ~]# cd repo/com/tensquare/
[root@jenkins tensquare]# ls
tensquare_common  tensquare_parentrz

在这里插入图片描述
再次进行构建
在这里插入图片描述
在这里插入图片描述
将剩下两个微服务打包
在这里插入图片描述

使用Dockerfile编译生成镜像

利用dockerfile-maven-plugin插件构建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>

在这里插入图片描述
在每个微服务项目根目录下建立Dockerfile文件
注意:每个项目公开的端口不一样
在这里插入图片描述

# 构建eureka服务器的dockerfile
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 10086
ENTRYPOINT ["java","-jar","/app.jar"]

修改Jenkins流水线脚本,添加dockerfile:build触发插件执行

// git凭证ID
def git_auth = "a4d0066f-6c58-4ab0-b714-6a24b3f5bc90"
// git的URL地址
def git_url = "git@192.168.100.240:tensquare_group/tensquare_back.git"node {stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}stage('代码审查') {// 定义当前Jenkins的SonarQubeScanner工具的环境,位于全局工具配置的SonarQube Scanner 的name定义为'sonar-scanner'def scannerHome = tool 'sonar-scanner'// 引用当前JenkinsSonarQube的环境,系统配置的SonarQube servers定义的name以及代码审查服务器位置withSonarQubeEnv('sonarqube') {sh """cd ${project_name}${scannerHome}/bin/sonar-scanner"""}}stage('编译安装公共子工程') {sh "mvn -f tensquare_common clean install"}stage('编译打包微服务工程') {// 项目参数传入的project_name 修改为变量sh "mvn -f ${project_name} clean package dockerfile:build"}
}

commit代码,然后对eureka_server进行构建
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
查看本地镜像,创建成功!
在这里插入图片描述
其他的服务也是如此,依然需要插件和dockerfile

# 编写dockerfile,注意端口号的区分,实际没多大区别# 构建tensquare_zuul所需的dockerfile
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 10020
ENTRYPOINT ["java","-jar","/app.jar"]# 构建tensquare_admin_service所需的dockerfile
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 9001
ENTRYPOINT ["java","-jar","/app.jar"]# 构建tensquare_gathering所需的dockerfile
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 9002
ENTRYPOINT ["java","-jar","/app.jar"]

上传代码后进行构建
在这里插入图片描述
在这里插入图片描述

上传到Harbor镜像仓库

修改Jenkinsfile构建脚本

添加对镜像打tag配置

// git凭证ID
def git_auth = "a4d0066f-6c58-4ab0-b714-6a24b3f5bc90"
// git的URL地址
def git_url = "git@192.168.100.240:tensquare_group/tensquare_back.git"
// 镜像的版本号
def tag = "latest"
// Harbor的url地址
def harbor_url = "192.168.100.251:85"
// 镜像库项目名称
def harbor_project = "tensquare"node {stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}stage('代码审查') {// 定义当前Jenkins的SonarQubeScanner工具的环境,位于全局工具配置的SonarQube Scanner 的name定义为'sonar-scanner'def scannerHome = tool 'sonar-scanner'// 引用当前JenkinsSonarQube的环境,系统配置的SonarQube servers定义的name以及代码审查服务器位置withSonarQubeEnv('sonarqube') {sh """cd ${project_name}${scannerHome}/bin/sonar-scanner"""}}stage('编译安装公共子工程') {sh "mvn -f tensquare_common clean install"}stage('编译打包微服务工程,上传镜像') {// 项目参数传入的project_name 修改为变量sh "mvn -f ${project_name} clean package dockerfile:build"// 定义镜像名称def imageName = "${project_name}:${tag}"// 对镜像打标签sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"}
}

在这里插入图片描述
在这里插入图片描述
添加Harbor用户凭证
在这里插入图片描述
创建完成后再次进入凭证查看
在这里插入图片描述
将生成的id复制并保存
在这里插入图片描述

5785fbf3-a0f0-4234-8961-c866ca1e7046

进入流水线片段生成器
在这里插入图片描述
在这里插入图片描述
编写Jenkins流水线脚本,添加推送镜像至harbor仓库的配置

// git凭证ID
def git_auth = "a4d0066f-6c58-4ab0-b714-6a24b3f5bc90"
// git的URL地址
def git_url = "git@192.168.100.240:tensquare_group/tensquare_back.git"
// 镜像的版本号
def tag = "latest"
// Harbor的url地址
def harbor_url = "192.168.100.251:85"
// 镜像库项目名称
def harbor_project = "tensquare"
// Harbor的登录凭证ID
def harbor_auth = "5785fbf3-a0f0-4234-8961-c866ca1e7046"node {stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}stage('代码审查') {// 定义当前Jenkins的SonarQubeScanner工具的环境,位于全局工具配置的SonarQube Scanner 的name定义为'sonar-scanner'def scannerHome = tool 'sonar-scanner'// 引用当前JenkinsSonarQube的环境,系统配置的SonarQube servers定义的name以及代码审查服务器位置withSonarQubeEnv('sonarqube') {sh """cd ${project_name}${scannerHome}/bin/sonar-scanner"""}}stage('编译安装公共子工程') {sh "mvn -f tensquare_common clean install"}stage('编译打包微服务工程,上传镜像') {// 项目参数传入的project_name 修改为变量sh "mvn -f ${project_name} clean package dockerfile:build"// 定义镜像名称def imageName = "${project_name}:${tag}"// 对镜像打标签sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"// 把镜像推送到Harbor,项目为私有级别,登录时涉及一个问题,登录harbor需要输入账号和密码,Jenkinsfile需要配置项目目录下,会暴露给所有开发人员,为了安全使用凭证方式withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {// 登录到Harbor,引用如上定义的username和password,就是用户haibo的信息sh "docker login -u ${username} -p ${password} ${harbor_url}"// 镜像上传sh "docker push ${harbor_url}/${harbor_project}/${imageName}"sh "echo 镜像上传成功"}}
}

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

拉取镜像和发布应用

安装Publish Over SSH插件

安装以下插件,可以实现远程发送Shell命令
在这里插入图片描述
在这里插入图片描述

配置远程部署服务器

# 将Jenkins服务器的公钥拷贝到远程pro生产部署服务器 
ssh-copy-id 192.168.100.252

在这里插入图片描述
在Jenkins进入系统配置,找到Publish over SSH
在这里插入图片描述
Path to key文件指向持续集成服务器的私钥文件,写绝对路径
在这里插入图片描述
点击新增
新增Hostname设置远程生产环境部署项目的主机IP地址
在这里插入图片描述
在这里插入图片描述
修改Jenkinsfile构建脚本

生成远程调用模板代码
新版Jenkins需要安装完插件后重启生效
在这里插入图片描述
在这里插入图片描述
其他置空,生成流水线脚本,需要注意的是Exec command,这个是远程执行的命令
在这里插入图片描述

sshPublisher(publishers: [sshPublisherDesc(configName: 'master_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)])

添加端口参数,作为外部可变参数进行设置

参数化构建过程–>字符参数
在这里插入图片描述
在这里插入图片描述

编写远程部署脚本

# 位于pro生产环境服务器上操作
mkdir /opt/jenkins_shell
vim /opt/jenkins_shell/deploy.sh#!/bin/sh
# 接收外部参数
harbor_url=$1
harbor_project_name=$2
project_name=$3
tag=$4
port=$5imageName=$harbor_url/$harbor_project_name/$project_name:$tagecho "$imageName"# 查询容器是否存在,存在则删除
containerId=`docker ps -a | grep -w ${project_name}:${tag}  | awk '{print $1}'`
if [ "$containerId" !=  "" ] ; then# 停掉容器docker stop $containerId# 删除容器docker rm $containerIdecho "成功删除容器"
fi# 查询镜像是否存在,存在则删除
imageId=`docker images | grep -w $project_name  | awk '{print $3}'`if [ "$imageId" !=  "" ] ; then# 删除镜像docker rmi -f $imageIdecho "成功删除镜像"
fi# 登录Harbor
docker login -u haibo -p LIUhaibo123 $harbor_url# 下载镜像
docker pull $imageName# 启动容器
docker run -di -p $port:$port $imageNameecho "容器启动成功"# 添加执行权限
chmod +x /opt/jenkins_shell/deploy.sh

编写Jenkins流水线脚本

添加远程部署配置

// git凭证ID
def git_auth = "a4d0066f-6c58-4ab0-b714-6a24b3f5bc90"
// git的URL地址
def git_url = "git@192.168.100.240:tensquare_group/tensquare_back.git"
// 镜像的版本号
def tag = "latest"
// Harbor的url地址
def harbor_url = "192.168.100.251:85"
// 镜像库项目名称
def harbor_project = "tensquare"
// Harbor的登录凭证ID
def harbor_auth = "5785fbf3-a0f0-4234-8961-c866ca1e7046"node {stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}stage('代码审查') {// 定义当前Jenkins的SonarQubeScanner工具的环境,位于全局工具配置的SonarQube Scanner 的name定义为'sonar-scanner'def scannerHome = tool 'sonar-scanner'// 引用当前JenkinsSonarQube的环境,系统配置的SonarQube servers定义的name以及代码审查服务器位置withSonarQubeEnv('sonarqube') {sh """cd ${project_name}${scannerHome}/bin/sonar-scanner"""}}stage('编译安装公共子工程') {sh "mvn -f tensquare_common clean install"}stage('编译打包微服务工程,上传镜像') {// 项目参数传入的project_name 修改为变量sh "mvn -f ${project_name} clean package dockerfile:build"// 定义镜像名称def imageName = "${project_name}:${tag}"// 对镜像打标签sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"// 把镜像推送到Harbor,项目为私有级别,登录时涉及一个问题,登录harbor需要输入账号和密码,Jenkinsfile需要配置项目目录下,会暴露给所有开发人员,为了安全使用凭证方式withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {// 登录到Harbor,引用如上定义的username和password,就是用户haibo的信息sh "docker login -u ${username} -p ${password} ${harbor_url}"// 镜像上传sh "docker push ${harbor_url}/${harbor_project}/${imageName}"sh "echo 镜像上传成功"}// 部署应用sshPublisher(publishers: [sshPublisherDesc(configName: 'master_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)])}
}

提交Jenkinsfile文件后尝试对项目进行构建
在这里插入图片描述
远程登录服务器并执行部署脚本
在这里插入图片描述
在生产环境部署服务器上查看容器和镜像
在这里插入图片描述
在这里插入图片描述

部署和测试所有微服务

更改微服务设置

eureka配置
修改ip地址为部署的生产环境服务器地址
在这里插入图片描述
zuul网关配置
修改eureka的ip地址,使其部署后在eureka服务器注册服务
在这里插入图片描述
admin_service权限中心
需要修改数据库相关信息(选择sonarqube服务器上的mysql作为后端数据库,此数据库在sonarqube代码审查服务器上)
在这里插入图片描述

# mysql授权root用户远程登录
grant all privileges on *.* to 'root'@'%' identified by 'Hahaha123@#';# 重载数据库刷新用户权限
flush privileges;

使用SQLyog进行连接测试
在这里插入图片描述
gathering活动微服务
同样修改数据库和eurekaIP地址使其部署后可以注册服务
在这里插入图片描述
将所有更新的配置上传代码仓库
在这里插入图片描述
导入MySQL数据
依次导入用户表和活动表
在这里插入图片描述
在这里插入图片描述
更改了配置后重新部署微服务

需要注意的是端口的区别
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
查看容器运行状态
在这里插入图片描述
通过浏览器查看
在这里插入图片描述
此时所有微服务已经全部构建完毕!可以通过postman对微服务功能进行检测
由于程序连接数据库有部分问题,通过参考文章:https://blog.csdn.net/L_it123/article/details/106845391 修改部分代码

首先检查权限中心能否登录

http://192.168.100.252:10020/admin/admin/login

在这里插入图片描述

部署前端静态web网站

在这里插入图片描述
安装Nginx服务器

rpm -ivh nginx-1.20.0-1.el7.ngx.x86_64.rpm# 修改端口
vim /etc/nginx/conf.d/default.conf
server {listen       9090;server_name  localhost;#access_log  /var/log/nginx/host.access.log  main;location / {root   /usr/share/nginx/html;index  index.html index.htm;}# 启动nginx
systemctl enable nginx --now

在这里插入图片描述

# 持续集成服务器安装nodejs环境
curl --silent --location https://rpm.nodesource.com/setup_10.x | bash -
yum install nodejs -y
npm install -g cnpm --registry=https://registry.npm.taobao.org

在这里插入图片描述
创建前端流水线项目
在这里插入图片描述
添加分支参数
在这里插入图片描述
在这里插入图片描述

编写流水线脚本

//gitlab的凭证 
def git_auth = "a4d0066f-6c58-4ab0-b714-6a24b3f5bc90"node {stage('拉取代码') {checkout scmGit(branches: [[name: '*/master']], extensions: [], userRemoteConfigs: [[credentialsId: "${branch}", url: 'git@192.168.100.240:tensquare_group/tensquare_front.git']])}stage('打包前端静态代码') {// 使用NodeJS的npm进行打包// sh 'npm cache clean --force'// sh 'rm -rf node_modules && rm -rf package-lock.json'  sh 'npm install'    sh 'npm run build'    }stage('部署网站') {	//=====以下为远程调用进行项目部署========sshPublisher(publishers: [sshPublisherDesc(configName: 'master_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 凭据需要去Jenkins找
在这里插入图片描述
在这里插入图片描述
构建成功
在这里插入图片描述
使用浏览器访问
在这里插入图片描述
在这里插入图片描述
查询到了数据库的信息,因此证明前端页面和后端连接成功
在这里插入图片描述
再次查看容器日志,可以看到有修改数据库内容,证明前后端连通成功

# 查看活动微服务容器日志
docker logs -f `docker ps| grep -i 'gathering'|awk '{print $1}'`

在这里插入图片描述
至此Jenkins+Docker+SpringCloud微服务持续集成就搭建完成!剩余还需要对其优化!

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

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

相关文章

RK3568蓝牙程序开发过程

1、搭建蓝牙开发环境 蓝牙开发可以使用C语言开发或python语言开发&#xff0c;使用的是蓝牙开发库为bluez库。 本文开发使用python语言开发&#xff0c;安装bluez库&#xff0c;可以使用pip install PyBluez来安装。 如果安装不上的话&#xff0c;可以使用sudo apt install pyt…

Kafka与Zookeeper版本对应关系

文章目录 了解版本对应Kafka安装包Kafka源码包 了解 比如&#xff1a; kafka_2.11-1.1.1.jar包 其中2.11表示的是Scala的版本&#xff0c;因为Kafka服务器端代码完全由Scala语音编写。”-“后面的1.1.1表示的kafka的版本信息。遵循一个基本原则&#xff0c;Kafka客户端版本和服…

无涯教程-Perl - getnetbyname函数

描述 此函数返回由NAME指定的网络信息(在列表context中)($name,$aliases,$addrtype,$net) 语法 以下是此函数的简单语法- getnetbyname NAME返回值 此函数在错误时返回undef,否则在标量context中返回网络地址,在错误时返回空列表,否则在列表context中返回网络记录(名称,别…

错误: XXXAdapter不是抽象的, 并且未覆盖Adapter中的抽象方法onBindViewHolder(ViewHolder,int)

一、问题描述 在学习Android可侧滑删除的RecyclerView的时候&#xff0c;遇到了下面的报错 错误: SwipeDelAdapter不是抽象的, 并且未覆盖Adapter中的抽象方法onBindViewHolder(ViewHolder,int) public class SwipeDelAdapter extends RecyclerView.Adapter { ^ 在上面的…

操作系统—调度算法

进程调度算法 进程调度算法也称CPU调度算法 调度发生时期 当进程从运行状态转到等待状态&#xff1b;当进程从运行状态转到就绪状态&#xff1b;当进程从等待状态转到就绪状态&#xff1b;当进程从运行状态转到终止状态&#xff1b; 其中发生在 1 和 4 两种情况下的调度称为…

物理层扩展以太网

扩展站点与集线器之间的距离&#xff1a;   在10BASE-T星型以太网中&#xff0c;可使用光纤和一对光纤调制解调器来扩展站点与集线器之间的距离。   为站点和集线器各增加一个用于电信号和光信息号转换的光纤调制解调器&#xff0c;以及他们之间的通信光纤。 扩展共享式以太…

Unity开发笔记:截取指定位置含有UI的场景截图并输出

学习记录整理&#xff0c;自用&#xff0c;也希望能帮助到有相同需求的人。 如果直接截全图&#xff1a; string screenshotName "Assets/Textures/UI/20230803/2.png";ScreenCapture.CaptureScreenshot(screenshotName);截取指定位置含有UI的场景截图&#xff1a; …

uniapp input输入框placeholder文本右对齐

input输入框placeholder文本右对齐 给input标签加上placeholder-class&#xff0c;这个是给placeholder设置样式&#xff0c;右对齐这就是text-align:right;字体颜色之类依次编辑即可。

flutter开发实战-TextPainter计算文本内容的宽度

flutter开发实战-TextPainter计算文本内容的宽度 最近开发过程中根据Text文本的大小判断是否需要进行显示跑马灯效果&#xff0c;获取文本的大小&#xff0c;需要TextPainter来获取Size 一、TextPainter TextPainter主要用于实现文本的绘制。TextPainter类可以将TextSpan渲染…

Babylon.js着色器简明简称【Shader】

推荐&#xff1a;用 NSDT设计器 快速搭建可编程3D场景 为了生成 BabylonJS 场景&#xff0c;需要用 Javascript 编写代码&#xff0c;BabylonJS 引擎会处理该代码并将结果显示在屏幕上。 场景可以通过改变网格、灯光或摄像机位置来改变。 为了及时显示可能的变化&#xff0c;屏…

【架构设计】如何设计一个高性能短链系统

一、前言 所谓系统设计&#xff0c;就是给一个场景&#xff0c;让你给出对应的架构设计&#xff0c;需要考虑哪些问题&#xff0c;采用什么方案解决。很多面试官喜欢出这么一道题来考验你的知识广度和逻辑思考能力。 虽然各个系统千差万别&#xff0c;但是设计思想基本一致&a…

Android Studio实现刮刮卡效果

代码和刮刮乐图片参考网络 实现效果 MainActivity import android.app.Activity; import android.os.Bundle;public class MainActivity extends Activity {Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentVi…

ruoyi-cloud微服务新建子模块

ruoyi-cloud微服务新建子模块 1、复制system模块 直接复制 modules下面已有的system模块&#xff0c;改名为 test 2、在modules下的 pom.xml文件中添加子模块 3、进入 test模块修改 pom.xml 把原有的system 修改成test 4、修改对应的包名、目录名和启动应用程序为test 5、修…

大学生口才培训需求分析

标题&#xff1a;大学生口才培训需求分析 摘要&#xff1a; 本论文旨在分析大学生口才培训的需求&#xff0c;通过对大学生口才培训的重要性、现状和挑战进行研究&#xff0c;并结合相关理论和实践经验&#xff0c;提出相应的培训需求和解决方案。通过本论文的研究&#xff0c…

介绍另外一个容器技术, Apptainer

一说到容器&#xff0c;我们往往会脱口而出&#xff0c; Docker&#xff0c; 实际上Docker 仅仅是Linux 容器化的一种&#xff0c; 今天介绍的Apptainer 就是另外一种容器技术。 那么Apptainer 具体是一个什么东西呢&#xff1f; 跟Docker 有什么区别呢&#xff1f; 首先&#…

【HarmonyOS】Java如何引用外部jar包

【关键字】 Java、引用jar包​ 【写在前面】 使用API6和API7开发HarmonyOS应用时&#xff0c;因为应用中只能引用SDK中开放的功能接口&#xff0c;但是部分jdk自带的接口功能在SDK中并未封装&#xff0c;要想在工程中使用jdk开放的接口功能&#xff0c;需要将jdk中的jar包通过…

【TS第三讲】完善TS开发环境

文章目录 &#x1f31f; 写在前面&#x1f31f; ts-node&#x1f31f; nodemon&#x1f31f; nodemon文件类型&#x1f31f; nodemon文件范围&#x1f31f; 写在最后 &#x1f31f; 写在前面 &#x1f525;探索TypeScript世界&#xff0c;驭Vue3Ts潮流&#xff0c;开启前端之旅…

STM32--综述

文章目录 前言STM32简介STM32F103C8T6系统结构Keil软件安装注意事项新建工程操作流程 前言 本专栏将学习B站江协科技的STM32入门教程&#xff0c;通过自身理解和对老师的总结所写的博客专栏。 STM32简介 STM32是意法半导体&#xff08;STMicroelectronics&#xff09;公司推…

intelJ IDEA\PHPStorm \WebStorm\PyCharm 通过ssh连接远程Mysql\Postgresql等数据库

最容易出错的地方是在general面板下的host&#xff0c;不应该填真实的host地址&#xff0c;而应该填localhost或者127.0.0.1 具体操作步骤见下图

Shopify平台Fulfillment业务模块升级

上图是销售订单、发货单与配送之间的关系图&#xff0c;销售订单可以创建多个发货单&#xff0c;多个发货单(不同销售订单)可以合并在一个配送订单进行发货 接口请求错误记录: 1. The api_client does not have the required permission(s). 2. Required parameter missing or…