Jenkins入门(二):流水线方式部署多模块Springboot项目

目录

一、环境准备

1. 搭建配置Jenkins  (在上一篇基础上进行)

2. 安装mysql

3. 安装redis

4. 配置docker-componse

 5. 启动docker-componse

二、脚本准备

1. Jenkinsfile

2. deploy.sh

3. Dockerfile

三、Jenkins流水线配置

新增版本号参数

流水线选择代码里面的Jenkinsfile相对路径

选择需要的分支构建任务

四、问题 

1. 多模块打包失败,不会自动打包依赖的其他模块

2. 华为云公网IP访问不通

参考:


一、环境准备

1. 搭建配置Jenkins  (在上一篇基础上进行)

Jenkins入门:从搭建到部署第一个Springboot项目(踩坑记录)-CSDN博客

2. 安装mysql

docker pull mysql:5.7

3. 安装redis

docker pull redis:5.0.14

4. 配置docker-componse

version: "3.8"
services:jenkins:image: jenkins/jenkins:ltscontainer_name: jenkinsrestart: alwaysprivileged: trueuser: rootvolumes:- /var/run/docker.sock:/var/run/docker.sock- /var/jenkins_home:/var/jenkins_home- /root/soft:/root/soft- /usr/bin/docker:/usr/bin/docker- /etc/docker/daemon.json:/etc/docker/daemon.jsonports:- "8080:8080"- "50000:50000"environment:TZ: Asia/Shanghaimysql: # 服务名称image: mysql:5.7 # 或其它mysql版本container_name: mysql5.7 # 容器名称environment:- MYSQL_ROOT_PASSWORD=123456 # root用户密码
#      - TZ=Asia/Shanghai # 设置容器时区 我这里通过下面挂载方式同步的宿主机时区和时间了,这里忽略volumes:- /var/mysql5.7/log:/var/log/mysql # 映射日志目录,宿主机:容器- /var/mysql5.7/data:/var/lib/mysql # 映射数据目录,宿主机:容器- /var/mysql5.7/conf:/etc/mysql/conf.d # 映射配置目录,宿主机:容器- /etc/localtime:/etc/localtime:ro # 让容器的时钟与宿主机时钟同步,避免时间的问题,ro是read only的意思,就是只读。    ports:- 3306:3306 # 指定宿主机端口与容器端口映射关系,宿主机:容器restart: always # 容器随docker启动自启redis: # 服务名称image: redis:5.0.14 # redis镜像版本container_name: redis5 # 容器名称ports:- 6379:6379 # 指定宿主机端口与容器端口映射关系,宿主机:容器volumes:- /var/redis5/conf/redis.conf:/etc/redis/redis.conf # 映射配置文件目录,宿主机:容器- /var/redis5/data:/data # 映射数据目录,宿主机:容器restart: always # 容器开机自启privileged: true # 获取宿主机root权限command: ["redis-server","/etc/redis/redis.conf"] # 指定配置文件启动redis-server进程

 5. 启动docker-componse

docker-compose up -d

二、脚本准备

参考项目目录:

1. Jenkinsfile

#!groovy
pipeline {agent anyenvironment {// 应用名称APP_NAME = 'xxx-server'// 应用部署路径(注意些自己的jenkins挂载目录)APP_DEPLOY_BASE_DIR = '/var/jenkins_home/workspace/'MODULE_NAME = "$project_name";}stages {stage('打印信息') {      //打印信息steps {echo '变量打印信息'echo "Project_Pipeline_name: $JOB_NAME"echo "workspace: $WORKSPACE"echo "branch: $branch_name"           //gitlab分支名echo "build_id: $BUILD_ID"}}stage('检出') {steps {git credentialsId: '0d104c96-f1bf-4992-97b2-6b70d6c938e4', url: 'https://gitee.com/xxx/xxx-framework.git',branch: "$branch_name"}}stage('构建') {steps {sh 'mvn clean package -Dmaven.test.skip=true'}}stage('部署') {steps {sh 'cp -f ' + ' script/shell/deploy.sh ' + "${env.APP_DEPLOY_BASE_DIR}" + "${env.APP_NAME}"+'/'sh 'cp -f ' + "${env.APP_NAME}" + '/target/*.jar ' + "${env.APP_DEPLOY_BASE_DIR}" + "${env.APP_NAME}" +'/build/'archiveArtifacts "${env.APP_NAME}" + '/target/*.jar'sh 'chmod +x ' + "${env.APP_DEPLOY_BASE_DIR}" + "${env.APP_NAME}" + '/deploy.sh'sh 'bash ' + "${env.APP_DEPLOY_BASE_DIR}" + "${env.APP_NAME}" + '/deploy.sh'}}
}
}

2. deploy.sh

注意:docker run -d -p 48080:48080 -v /root/soft/logs:/user/logs $SERVER_NAME,log目录挂载,否则日志无法保存到宿主机

#!/bin/bash
set -eDATE=$(date +%Y%m%d%H%M)
# 基础路径
BASE_PATH=/var/jenkins_home/workspace/hbintrade-server
# 编译后 jar 的地址。部署时,Jenkins 会上传 jar 包到该目录下
SOURCE_PATH=$BASE_PATH/build
# 服务名称。同时约定部署服务的 jar 包名字也为它。
SERVER_NAME=hbintrade-server
# 环境
PROFILES_ACTIVE=dev
# 健康检查 URL
HEALTH_CHECK_URL=http://xxxx:48080/actuator/health/# heapError 存放路径
HEAP_ERROR_PATH=$BASE_PATH/heapError
# JVM 参数
JAVA_OPS="-Xms512m -Xmx512m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$HEAP_ERROR_PATH"# SkyWalking Agent 配置
#export SW_AGENT_NAME=$SERVER_NAME
#export SW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.0.84:11800
#export SW_GRPC_LOG_SERVER_HOST=192.168.0.84
#export SW_AGENT_TRACE_IGNORE_PATH="Redisson/PING,/actuator/**,/admin/**"
#export JAVA_AGENT=-javaagent:/work/skywalking/apache-skywalking-apm-bin/agent/skywalking-agent.jar# 备份
function backup() {# 如果不存在,则无需备份if [ ! -f "$BASE_PATH/$SERVER_NAME.jar" ]; thenecho "[backup] $BASE_PATH/$SERVER_NAME.jar 不存在,跳过备份"# 如果存在,则备份到 backup 目录下,使用时间作为后缀elseecho "[backup] 开始备份 $SERVER_NAME ..."cp $BASE_PATH/$SERVER_NAME.jar $BASE_PATH/backup/$SERVER_NAME-$DATE.jarecho "[backup] 备份 $SERVER_NAME 完成"fi
}# 最新构建代码 移动到项目环境
function transfer() {echo "[transfer] 开始转移 $SERVER_NAME.jar"# 删除原 jar 包if [ ! -f "$BASE_PATH/$SERVER_NAME.jar" ]; thenecho "[transfer] $BASE_PATH/$SERVER_NAME.jar 不存在,跳过删除"elseecho "[transfer] 移除 $BASE_PATH/$SERVER_NAME.jar 完成"rm $BASE_PATH/$SERVER_NAME.jarfi# 复制新 jar 包echo "[transfer] 从 $SOURCE_PATH 中获取 $SERVER_NAME.jar 并迁移至 $BASE_PATH ...."cp $SOURCE_PATH/$SERVER_NAME.jar $BASE_PATHecho "[transfer] 转移 $SERVER_NAME.jar 完成"
}# 停止:优雅关闭之前已经启动的服务
function stop() {echo "[stop] 开始停止 $BASE_PATH/$SERVER_NAME"PID=$(ps -ef | grep $BASE_PATH/$SERVER_NAME | grep -v "grep" | awk '{print $2}')# 如果 Java 服务启动中,则进行关闭if [ -n "$PID" ]; then# 正常关闭echo "[stop] $BASE_PATH/$SERVER_NAME 运行中,开始 kill [$PID]"kill -15 $PID# 等待最大 120 秒,直到关闭完成。for ((i = 0; i < 120; i++))dosleep 1PID=$(ps -ef | grep $BASE_PATH/$SERVER_NAME | grep -v "grep" | awk '{print $2}')if [ -n "$PID" ]; thenecho -e ".\c"elseecho "[stop] 停止 $BASE_PATH/$SERVER_NAME 成功"breakfidone# 如果正常关闭失败,那么进行强制 kill -9 进行关闭if [ -n "$PID" ]; thenecho "[stop] $BASE_PATH/$SERVER_NAME 失败,强制 kill -9 $PID"kill -9 $PIDfi# 如果 Java 服务未启动,则无需关闭elseecho "[stop] $BASE_PATH/$SERVER_NAME 未启动,无需停止"fi
}# 启动:启动后端项目
function start() {# 开启启动前,打印启动参数echo "[start] 开始启动 $BASE_PATH/$SERVER_NAME"echo "[start] JAVA_OPS: $JAVA_OPS"echo "[start] JAVA_AGENT: $JAVA_AGENT"echo "[start] PROFILES: $PROFILES_ACTIVE"echo "[docker] 构建镜像"docker stop $SERVER_NAME || truedocker rm $SERVER_NAME || truedocker rmi $SERVER_NAME || truedocker build -t $SERVER_NAME:latest ./hbintrade-server/echo "[docker] 构建镜像完成"docker run -d -p 48080:48080 -v /root/soft/logs:/user/logs $SERVER_NAMEecho "[docker] 项目启动完成"# 开始启动
#    echo "[start] 开始启动 BUILD_ID=dontKillMe nohup java -server $JAVA_OPS -jar $BASE_PATH/$SERVER_NAME.jar --spring.profiles.active=$PROFILES_ACTIVE &"
#    BUILD_ID=dontKillMe nohup java -server $JAVA_OPS -jar $BASE_PATH/$SERVER_NAME.jar --spring.profiles.active=$PROFILES_ACTIVE &
#    echo "[start] 启动 $BASE_PATH/$SERVER_NAME 完成"
}# 健康检查:自动判断后端项目是否正常启动
function healthCheck() {# 如果配置健康检查,则进行健康检查if [ -n "$HEALTH_CHECK_URL" ]; then# 健康检查最大 120 秒,直到健康检查通过echo "[healthCheck] 开始通过 $HEALTH_CHECK_URL 地址,进行健康检查";for ((i = 0; i < 120; i++))do# 请求健康检查地址,只获取状态码。result=`curl -I -m 10 -o /dev/null -s -w %{http_code} $HEALTH_CHECK_URL || echo "000"`# 如果状态码为 200,则说明健康检查通过if [ "$result" == "200" ]; thenecho "[healthCheck] 健康检查通过";break# 如果状态码非 200,则说明未通过。sleep 1 秒后,继续重试elseecho -e ".\c"sleep 1fidone# 健康检查未通过,则异常退出 shell 脚本,不继续部署。if [ ! "$result" == "200" ]; thenecho "[healthCheck] 健康检查不通过,可能部署失败。查看日志,自行判断是否启动成功";tail -n 10 nohup.outexit 1;# 健康检查通过,打印最后 10 行日志,可能部署的人想看下日志。elsetail -n 10 nohup.outfi# 如果未配置健康检查,则 sleep 120 秒,人工看日志是否部署成功。elseecho "[healthCheck] HEALTH_CHECK_URL 未配置,开始 sleep 120 秒";sleep 120echo "[healthCheck] sleep 120 秒完成,查看日志,自行判断是否启动成功";tail -n 50 nohup.outfi
}# 部署
function deploy() {cd $BASE_PATH# 备份原 jar
#    backup# 停止 Java 服务stop# 部署新 jar
#    transfer# 启动 Java 服务start# 健康检查healthCheck
}deploy

参考: 

Spring boot——Actuator 详解 - 曹伟雄 - 博客园 (cnblogs.com) 

3. Dockerfile

在server模块下

## AdoptOpenJDK 停止发布 OpenJDK 二进制,而 Eclipse Temurin 是它的延伸,提供更好的稳定性
## 感谢复旦核博士的建议!灰子哥,牛皮!
FROM eclipse-temurin:8-jre## 创建目录,并使用它作为工作目录
RUN mkdir -p /hbintrade-server
WORKDIR /hbintrade-server
## 将后端项目的 Jar 文件,复制到镜像中
COPY ./target/hbintrade-server.jar app.jar## 设置 TZ 时区
ENV TZ=Asia/Shanghai
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
ENV JAVA_OPTS="-Xms512m -Xmx512m -Djava.security.egd=file:/dev/./urandom"## 应用参数
ENV ARGS=""## 暴露后端项目的 48080 端口
EXPOSE 48080## 启动后端项目
CMD java ${JAVA_OPTS} -jar app.jar $ARGS --spring.profiles.active=dev

三、Jenkins流水线配置

下载插件Extended Choice Parameter Plugin

新增版本号参数

流水线选择代码里面的Jenkinsfile相对路径

选择需要的分支构建任务

四、问题 

1. 多模块打包失败,不会自动打包依赖的其他模块

解决:flatten-maven-plugin统一版本打包失败问题记录-CSDN博客

2. 华为云公网IP访问不通

解决:华为云服务器公网ip访问不通解决-CSDN博客

参考:

  • Jenkins流水线--部署多模块maven项目(推荐) - 简书 (jianshu.com)
  • 使用docker-compose部署Redis(单机部署)_docker-compose redis单机-CSDN博客
  • 使用docker-compose 部署 MySQL(所有版本通用)_docker compose mysql-CSDN博客
  • 若依微服务集群搭建及jenkins自动化集群部署_若衣微服务版jekens-CSDN博客

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

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

相关文章

游戏逆向基础-找释放技能CALL

思路&#xff1a;通过send断点然后对send的data参数下写入断点找到游戏里面的技能或者攻击call 进入游戏先选好一个怪物&#xff08;之所以要先选好是因为选怪也会断&#xff0c;如果直接左键打怪的话就会断几次&#xff09; 断下来后对参数下硬件写入断点 硬件断点断下来后先…

Java | Leetcode Java题解之第475题供暖器

题目&#xff1a; 题解&#xff1a; class Solution {public int findRadius(int[] houses, int[] heaters) {Arrays.sort(houses);Arrays.sort(heaters);int ans 0;for (int i 0, j 0; i < houses.length; i) {int curDistance Math.abs(houses[i] - heaters[j]);whil…

【工具篇】MLU运行XInference部署手册

文章目录 前言一、平台环境准备二、代码下载三、安装部署1.正常pip 安装 四、运行结果展示1.如果界面404或没有东西请这样做2.运行效果 前言 Xorbits Inference&#xff08;Xinference&#xff09;是一个功能强大、用途广泛的库&#xff0c;旨在为语言、语音识别和多模态模型提…

Python | Leetcode Python题解之第478题在圆内随机生成点

题目&#xff1a; 题解&#xff1a; class Solution:def __init__(self, radius: float, x_center: float, y_center: float):self.xc x_centerself.yc y_centerself.r radiusdef randPoint(self) -> List[float]:u, theta random.random(), random.random() * 2 * mat…

js简单基础笔记

一 . js特点 1. Js是一门解释型语言&#xff0c;不用编译&#xff0c;而是直接执行 2. js是一门动态语言&#xff0c;其中的任何内容都是不确定的 3. 语法结构和Java&#xff0c;c都很像 4. ​ js是一门面向对象的语言 5.js严格区分大小写 二 . js使用 1…

【AI知识】距离度量和相似性度量的常见算法

本文介绍一些AI中常见的距离度量和相似性度量算法&#xff1a; 1. 欧几里得距离&#xff08;Euclidean Distance&#xff09; 欧几里得距离是最常见的距离度量方法&#xff0c;用来计算两个向量之间的“直线距离”&#xff0c;也被成为L2范数。 公式如下&#xff0c;其中 x…

6、ES6

文章目录 一.关于ES6二.关于变量声明let声明变量const 声明常量 三.变量的解构赋值四.字符串的扩展五.函数的扩展函数默认参数rest参数箭头函数(函数的新写法) 六.数组的扩展七.对象的扩展语法上的简化对象的解构赋值 八.Symbol&#xff1a;新的数据类型(类似于字符串)独一无二…

学习中,师傅b站泷羽sec——xss挖掘过程

某职业技术学院网站xss挖掘&#xff1a; 资产归纳 例如&#xff1a;先把功能点都看一遍&#xff0c;大部分都是文章 根据信息搜集第一课学习到一般主站的防御力是比较强的&#xff0c;出现漏洞的点不是对新手不友好。 在资产验证过程中还是把主站看了一遍 没有发现有攻击的机会…

未来人工智能的发展对就业市场的影响 人工智能在生活中的相关

人工智能&#xff08;Artificial Intelligence&#xff09;&#xff0c;英文缩写为AI.是新一轮科技革命和产业变革的重要驱动力量&#xff0c; 是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学. 人工智能的发展对就业市场的影响主要…

论文笔记:RelationPrompt :Zero-Shot Relation Triplet Extraction

论文来源: ACL Findings 2022 论文链接:https://arxiv.org/pdf/2203.09101.pdf 论文代码:http://github.com/declare-lab/RelationPrompt 本篇论文是由阿里达摩院自然语言智能实验室于2022年发表的关于零样本关系抽取的顶会论文,本篇博客将记录我在阅读过程中的一些笔记…

修改pq_default.ini禁用降噪,解决S905X3电视盒硬解视频画质模糊、严重涂抹得像油画、水彩画的问题

笔者使用一台处理器芯片为 S905X3 的电视盒将近一年&#xff0c;性能比之前的 RK3328 的盒子有所提升&#xff0c;但我对它视频解码方面感到越来越不爽&#xff0c;该盒子的硬解视频总是开启美颜降噪和锐化&#xff0c;导致硬解视频的画质模糊&#xff0c;细节都被磨平&#xf…

使用Jenkins部署项目

部署中的痛点 为什么要用Jenkins&#xff1f;我说下我以前开发的痛点&#xff0c;在一些中小型企业&#xff0c;每次开发一个项目完成后&#xff0c;需要打包部署&#xff0c;可能没有专门的运维人员&#xff0c;只能开发人员去把项目打成一个exe包&#xff0c;可能这个项目已…

OPENSSL-2023/11/10学习记录-C/C++对称分组加密DES

对称分组加密常用算法&#xff1a; DES 3DES AES 国密SM4 对称分组加密应用场景&#xff1a; 文件或者视频加密 加密比特币私钥 消息或者配置项加密 SSL通信加密 对称分组加密 使用异或实现一个简易的对称加密算法 A明文 B秘钥 AB密文AB (AB)B A 密码补全和初始化 数…

第六节——从深层剖析qsort的使用(让你不再害怕指针)

文章目录 1.什么是回调函数2.qsort的使用qsort排序整形数据qsort排序结构体数据qsort排序字符串数据 3.qsort的模拟实现 1.什么是回调函数 回调函数就是⼀个通过函数指针调用的函数。 如果你把函数的指针&#xff08;地址&#xff09;作为参数传递给另⼀个函数&#xff0c;当…

Python画笔案例-087 绘制 旋转的文字

1、绘制 旋转的文字 通过 python 的turtle 库绘制 旋转的文字,如下图: 2、实现代码 绘制 旋转的文字,以下为实现代码: """旋转的文字.py """ import time from turtle import * from write_patch import *screen = Screen

【JPCS独立出版 | 福州大学主办 | 有确定的ISSN号】第三届可再生能源与电气科技国际学术会议(ICREET 2024)

第三届可再生能源与电气科技国际学术会议&#xff08;ICREET 2024&#xff09; 2024 3rd International Conference on Renewable Energy and Electrical Technology ICREET 2024已成功申请JPCS - Journal of Physics: Conference Series (ISSN:1742-6596) 独立出版&#xf…

架构设计笔记-16-嵌入式系统架构设计理论与实践

目录 知识要点 嵌入式微处理器 存储器&#xff08;memory&#xff09; 内&#xff08;外&#xff09;总线逻辑 嵌入式操作系统&#xff08;Embedded Operating System&#xff0c;EOS&#xff09; 通用中间件 嵌入式中间件的一般架构 典型嵌入式中间件系统 案例分析 1…

搭建mongodb单机部署-认证使用

搭建mongodb单机部署-认证使用 实现思路 先将配置文件配置好&#xff0c;使用不用认证的启动命令启动docker&#xff0c;然后创建账号并制定角色。在使用开启认证的命令重新启动容器就好。 这里我并没有说先停止容器&#xff0c;删掉容器重新创建容器。是因为我的启动命令中…

机器学习—Motivations

学习了线性回归&#xff0c;它预测了一个数字&#xff0c;接下来学习分类&#xff0c;输入变量y只能接收少数几个可能的值中的一个&#xff0c;而不是无限范围内的任何数字。事实证明&#xff0c;线性回归不是分类问题的好算法。这将引入一种不同的算法&#xff0c;叫做Logisti…

立仪科技:光谱共焦传感器精准测量玻璃

光谱共焦测量技术作为一种创新的光学检测方法&#xff0c;近年来在工业领域引起了广泛关注。 它以其高精度、非接触式的特点&#xff0c;特别适用于透明或半透明材料如玻璃的厚度和表面形貌测量。 接下来&#xff0c;立仪科技小编将深入探讨光谱共焦技术在玻璃测量上的应用及其…