芝法酱学习笔记(0.7)——harbor与项目容器化部署

前言

之前我们主要讲的jar包部署。使用jar包部署可能导致不同服务互相争抢资源(隔离性),不同服务可能需要不同的jdk环境,有时也会造成困扰。故在微服务时代,我们通常使用docker部署

一、docker安装

docke相关的知识,其实之前文章也写过,本节主要讲harbor的安装以及与jenkins配合,做容器化部署。故docker相关的讨论会尽可能简略。

1.1 docker安装

安装官方文档的介绍安装即可

1.2 docker-compose安装

docker-compose相关内容,之前文章也写过,故知识点本次略过。

sudo apt-get update
sudo apt-get install docker-compose-plugin
curl -SL https://github.com/docker/compose/releases/download/v2.29.6/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

二、harbor安装

2.1 下载解压

首先,去官网下载离线包,然后拷到/WORK/DOWNLOADS文件夹内
使用以下命令解压:

tar -xzf harbor-offline-installer-v2.9.1.tgz

2.2 nginx配置证书

由于harbor更倾向于用https,所以需要配置nginx的证书

openssl genrsa -out /WORK/APP/nginx/cert/nginx-selfsigned.key 2048 
openssl req -new -key /WORK/APP/nginx/cert/nginx-selfsigned.key -ou
t /WORK/APP/nginx/cert/nginx-selfsigned.csr
openssl x509 -req -days 3650 -in /WORK/APP/nginx/cert/nginx-selfsigned.csr -signkey /WORK/APP/nginx/cert/nginx-selfsigned.key -out /WORK/APP/nginx/cert/nginx-selfsigned.crt -subj "/CN=192.168.0.64"

然后把location部分的配置,单独拎一个文件出来,比如叫shared.conf
分别在http和https的server模块include进来

include /WORK/APP/nginx/conf/shared.conf;

即可完成https的配置。

2.3 harbor配置

编辑harbor.yml,重点编辑以下内容

http:# 把端口设置成9090port: 9090
# 你没看错,这些先注释掉
#https:# https port for harbor, default is 443#port: 443# The path of cert and key files for nginx#certificate: /WORK/APP/nginx/cert/nginx-selfsigned.crt#private_key: /WORK/APP/nginx/cert/nginx-selfsigned.key
./prepare
./install

这样harbor就装好了。稍微解释一下,./prepare脚本,就是根据harbor.yml的配置,在当前目录生成相应的配置文件。而install命令,则是创建启动镜像。

2.3.1 安装番外

我尝试了把harbor放在nginx后面,最后还是失败了。
因为harbor的前端访问路径貌似无法配置,这就导致静态资源的加载全部出错。有哪位大佬知道怎么搞的可以私信或评论区回复。

三、docker化项目

3.1 创建一个dockerfile

我们接着之前的项目继续开发。之前的项目已经完成了lib,resource,config等与jar包的分离,并且以shell脚本启动项目,而非直接java -jar,我们的容器化也要支持这些功能(自讨苦吃式学习)。dockerfile创建如下所示
在这里插入图片描述

FROM openjdk:17-jdk-slimENV PORT="8081"RUN mkdir -p /app
WORKDIR /app
EXPOSE 8081
ADD ./target/nbr.jar nbr.jar
ADD ./target/bin bin
RUN chmod +x bin/startup.sh
RUN chmod +x bin/shutdown.sh
VOLUME ["/app/config","/app/resources","/app/logs","/app/lib"]
WORKDIR "/app/bin"
CMD ./startup.sh -p $PORT

需要注意的是,VOLUME 字段表示容器卷,docker中先声明,docker run时再映射到宿主机上。如果这里不声明,docker run -v 的时候就不好用了。

3.2 新的jenkins脚本

很多人搞容器化的时候,喜欢使用docker的maven插件来实现。然而实际上,并没有这种必要。学习成本又高,还有很多限制,也不好调试。不如直接在jenkins里写命令实现。变量向dockerfile传递,可以用–env var_key=var_value来实现。

参数名默认值描述
profiletest环境
appNameapp001部署文件夹
port8081端口
version1.0.0版本
isBuildImgtrue是否编译镜像
isUpdateBinfalse是否更新bin
isUpdateConfigfalse是否更新配置文件
isUpdateLibfalse是否更新lib包
isUpdateStaticfalse是否更新静态资源
isUpdateMapperfalse是否更新mapper
gitTagmastergit分支
import java.text.SimpleDateFormatnode{def remote = [:]remote.name = '地下室主机'remote.host = '192.168.0.64'remote.user = 'root'remote.password = '???@1314'remote.deploymentHome = "/WORK/APP/study2024-class006"remote.allowAnyHosts = trueremote.harbor = "localhost:9090"def app = [:]app.codePath = "busy"app.name = "study2024-class006"app.module = "nbr"app.version = "${version}"app.cd = "${appName}"app.port = "${port}"def timestamp = currentBuild.getTimeInMillis()def formattedTimestamp = new SimpleDateFormat("yyyy-MM-dd-HH_mm_ss").format(timestamp)stage("拉取代码"){git branch: "${gitTag}", credentialsId: 'gitSec', url: 'https://gitee.com/hataksumo/study2024-class006.git'}if(isCompileImage == "true"){stage("编译代码"){sh """cd busymvn cleanmvn package -pl ${app.module} -am -P${profile} -Dmaven.test.skip=true"""}stage("创建镜像"){sh """cd ${app.codePath}/${app.module}docker build -f docker/Dockerfile \--build-arg PORT=${app.port} \-t ${app.name}-${app.module}:${app.version} .docker tag ${app.name}-${app.module}:${app.version} ${remote.harbor}/library/${app.name}-${app.module}:${app.version}docker login localhost:9090 -u admin -p Harbor12345docker push ${remote.harbor}/library/${app.name}-${app.module}:${app.version}docker logout ${remote.harbor}/library/${app.name}-${app.module}:${app.version}docker image rm -f ${remote.harbor}/library/${app.name}-${app.module}:${app.version}docker image rm -f ${app.name}-${app.module}:${app.version}"""}}stage("拷贝资源"){echo "拷贝创建"sshCommand remote: remote, failOnError:false, command: """[ -d ${remote.deploymentHome}/${app.cd}] || mkdir -p ${remote.deploymentHome}/${app.cd}cd ${remote.deploymentHome}/${app.cd}[ -d lib] || mkdir -p lib[ -d config] || mkdir -p config[ -d resources/static] || mkdir -p resources/static[ -d resources/templates] || mkdir -p resources/templates[ -d resources/mybatis] || mkdir -p resources/mybatis"""if(isUpdateConfig == "true"){echo "删除config"sshRemove remote: remote, failOnError:false, path: "${remote.deploymentHome}/${app.cd}/config"echo "拷贝lib包"sshPut remote: remote, from: "${app.codePath}/${app.module}/target/config", into: "${remote.deploymentHome}/${app.cd}"}if(isUpdateLib == "true"){echo "删除lib包"sshRemove remote: remote, failOnError:false, path: "${remote.deploymentHome}/${app.cd}/lib"echo "拷贝lib包"sshPut remote: remote, from: "${app.codePath}/${app.module}/target/lib", into: "${remote.deploymentHome}/${app.cd}"}sshCommand remote: remote, failOnError:false, command: "mkdir ${remote.deploymentHome}/${app.cd}/resources"if(isUpdateStatic == "true"){echo "清除resources/static文件"sshRemove remote: remote, failOnError:false, path: "${remote.deploymentHome}/${app.cd}/resources/static"echo "拷贝static文件"sshPut remote: remote, from: "${app.codePath}/${app.module}/target/resources/static", into: "${remote.deploymentHome}/${app.cd}/resources"}if(isUpdateMapper == "true"){echo "清除resources/mybatis文件"sshRemove remote: remote, failOnError:false, path: "${remote.deploymentHome}/${app.cd}/resources/mybatis"echo "拷贝mybatis文件"sshPut remote: remote, from: "${app.codePath}/${app.module}/target/resources/mybatis", into: "${remote.deploymentHome}/${app.cd}/resources"}}stage("镜像拉取"){//docker stop ${app.name}-${app.module}-${appName}//此处是不优雅的关闭sshCommand remote: remote, failOnError:false, command: """docker image rm -f ${remote.harbor}/library/${app.name}-${app.module}:${app.version}docker container rm -f ${app.name}-${app.module}-${appName}docker login localhost:9090 -u admin -p Harbor12345docker pull ${remote.harbor}/library/${app.name}-${app.module}:${app.version}docker tag ${remote.harbor}/library/${app.name}-${app.module}:${app.version} ${app.name}-${app.module}:${app.version}docker logoutecho "docker run -it -p ${app.port}:${app.port} --volume ${remote.deploymentHome}/${app.cd}/config:/app/config --volume ${remote.deploymentHome}/${app.cd}/resources:/app/resources --volume ${remote.deploymentHome}/${app.cd}/logs:/app/logs --volume ${remote.deploymentHome}/${app.cd}/lib:/app/lib --env PORT=${app.port} ${app.name}-${app.module}:${app.version} bin/bash"docker run -d \-p ${app.port}:${app.port} \--volume ${remote.deploymentHome}/${app.cd}/config:/app/config \--volume ${remote.deploymentHome}/${app.cd}/resources:/app/resources \--volume ${remote.deploymentHome}/${app.cd}/logs:/app/logs \--volume ${remote.deploymentHome}/${app.cd}/lib:/app/lib \--env PORT=${app.port} \--name ${app.name}-${app.module}-${appName} \${app.name}-${app.module}:${app.version}echo "容器启动完成"lsof -i:${app.port}"""}}

3.3 错误处理

3.3.1 调试容器

如果项目启动不成功,可以使用docker run -it <镜像名> /bin/bash 进入容器调试

3.3.2 脚本启动的坑

docker的机制,如果执行的脚本没有阻塞,就会退出容器。所以需要在脚本的最后添加这样一句

tail -f "${BASE_DIR}/logs/start.out"

3.3.3 注意运行在容器内

无论是mysql还是redis等中间件的链接,记得不要配localhost,配成内网ip

四、代码展示

还请众道友移步我的码云

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

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

相关文章

新硬盘第一次使用需要怎样做?

无论是组装新电脑&#xff0c;还是给现有电脑增加存储空间&#xff0c;我们需要进行一些安装硬盘和设置硬盘的操作。对于没有相关经验的用户来说&#xff0c;对于拿到手的新硬盘会感到手足无措&#xff0c;不知道应该从哪里开始。今天小编详细介绍一下新硬盘第一次使用时的流程…

Qt-窗口布局按钮输入类

1. 窗口布局 Qt 提供了很多摆放控件的辅助工具&#xff08;又称布局管理器或者布局控件&#xff09;&#xff0c;它们可以完成两件事&#xff1a; 自动调整控件的位置&#xff0c;包括控件之间的间距、对齐等&#xff1b; 当用户调整窗口大小时&#xff0c;位于布局管理器内的…

AI没有是非观的原因

人工智能没有价值观的原因主要可以归结为只有数据驱动的被动性相关算法&#xff0c;没有主动干预性及其反事实关系&#xff1a; &#xff08;1&#xff09;数据被动驱动 AI的学习、分析、预测只依赖于大量的数据&#xff0c;并通过模式识别和统计分析建立关联。而这些数据本身可…

【算法】链表:2.两数相加(medium)+模拟

系列专栏 《分治》 《模拟》 《Linux》 目录 1、题目链接 2、题目介绍 3、解法 (模拟) 4、代码 1、题目链接 2. 两数相加 - 力扣&#xff08;LeetCode&#xff09; 2、题目介绍 3、解法 (模拟) 理解题目要求&#xff1a; 我们有两个链表&#xff0c;每个链表代表一个…

51单片机-第十四节-AD/DA(XPT2046触摸屏)

一、AD/DA介绍&#xff1a; AD&#xff1a;模拟-数字转换&#xff0c;将模拟信号转换为计算机可操作的数字信号。 DA&#xff1a;数字-模拟转换&#xff0c;将计算机输出的数字信号转换为模拟信号。 二、运算放大器&#xff1a; 1.介绍&#xff1a; &#xff08;1&#xf…

给网站加加速!下一代CDN(EdgeOne/边缘安全加速)使用与配置体验

随着访问量的增加和用户需求的多样化&#xff0c;服务器的带宽有限&#xff0c;面对一些图片数据&#xff0c;显得“力不从心”。CDN技术&#xff0c;就很好的解决了这个问题&#xff0c;但是价格也是用户思考的问题。 EdgeOne不仅继承了传统CDN的核心优势&#xff0c;更在速度…

uni-app 开发的应用快速构建成鸿蒙原生应用

uni-app 是一个使用 Vue.js 开发所有前端应用的框架&#xff0c;它支持编译到 iOS、Android、小程序等多个平台。对于 HarmonyOS&#xff08;鸿蒙系统&#xff09;&#xff0c;uni-app 提供了特定的支持&#xff0c;允许开发者构建鸿蒙原生应用。 一、uni-app 对 HarmonyOS 的支…

【用户管理 添加用户 超级用户 用户和组】

用户管理 添加用户超级用户用户和组 添加用户 介绍用户的管理操作 比如&#xff0c;添加一个用户 sudo useradd -m test1 其中&#xff0c;sudo表示管理员身份运行 修改用户密码 sudo passwd test1 删除用户 sudo userdel test 超级用户 1.首次使用时&#xff0c;需要给roo…

以光塑形:光固化3D打印机原理图文解析

公众号端&#xff1a; 光固化打印机介绍https://mp.weixin.qq.com/s?__bizMzkwMjc0MTE3Mw&mid2247484073&idx1&sn0d0fd026b373b06cd7c340ec8f56a006&chksmc0a1af73f7d62665a632baebbde4e5e00ffb9c6bd31bf547b4a86855d5524535619a6175a428#rd 光固化打印机…

IDEA上Mybatis介绍和使用

MyBatis是一款优秀的持久层框架&#xff0c;用于简化JDBC的开发。 创建项目 在springboot项目中添加Mybatis和MySQL依赖项。 找到数据库选项&#xff0c;点击新建 -> 数据库源&#xff0c;选择MySQL。 输入完成信息后&#xff0c;可以先进行测试&#xff0c;可以成功连接再…

逻辑回归LogisticRegression

一、逻辑回归的基础介绍 逻辑回归是一个分类模型 它可以用来预测某件事发生是否能够发生。分类问题是生活中最常见的问题&#xff1a; 生活中&#xff1a;比如预测上证指数明天是否会上涨&#xff0c;明天某个地区是否会下雨&#xff0c;西瓜是否熟了 金融领域&#xff1a;…

p20 docker自己commit一个镜像 p21 容器数据卷 p22mysql同步数据(国内镜像被封锁暂时往后放)p23具名挂载和匿名挂载

如何自己commit一个镜像 这里还是先引用一下老师的笔记 关于如何自己commit一个镜像这个问题目前因为从仓库中拉下来的Tomcat里面是没有项目的&#xff0c;所以把webapps.dist里面的拷贝到webapps里面去作为自己的镜像在commit一下 这里用Tomcat举例子首先把镜像拉取下来执…

MySql数据库---存储过程

存储过程概念 MySQL 5.0 版本开始支持存储过程。 简单的说&#xff0c;存储过程就是一组SQL语句集&#xff0c;功能强大&#xff0c;可以实现一些比较复杂的逻辑功能&#xff0c;类似于JAVA语言中的方法&#xff0c;类似Python中的函数&#xff1b; 存储过就是数据库 SQL 语言…

多项目管理怎么进行❓看这篇就够了

多项目管理是一个复杂而细致的过程&#xff0c;涉及多个项目的同时进行和协调。首先&#xff0c;明确每个项目的目标和范围至关重要。在项目开始之初&#xff0c;应对所有项目进行全面评估&#xff0c;确定其战略价值、影响范围和资源需求。这有助于为每个项目设定清晰的优先级…

反应香精市场报告:预计2030年全球市场规模将达到264.3亿美元

“反应香精”通常是指通过在食品或饮料加工过程中发生的物理、化学或酶反应而产生的风味剂。可以有意添加这些香料以增强最终产品的味道、香气或其他感官方面。它们通常用于食品和饮料行业&#xff0c;以保持一致性、提高适口性或创造独特的风味特征。生产工艺香料的方法有多种…

新网站做谷歌SEO为什么短期内很难看到显著效果?

对于一个全新的网站来说&#xff0c;SEO的效果往往不会在短期内显现。这是因为SEO需要时间来积累权重和信任度。谷歌对新网站通常会有一个观察期&#xff0c;在这段时间内&#xff0c;网站的表现不稳定&#xff0c;排名也会波动较大&#xff0c;这是正常情况&#xff0c;这时候…

excel表格转换为在线成绩查询怎么制作?

在当前“双减”政策的背景下&#xff0c;学生的考试成绩不再被公开展示&#xff0c;这是对学生隐私的一种保护。然而&#xff0c;这同时也带来了一个新的问题&#xff1a;家长们对于孩子成绩的关切并未减少&#xff0c;他们依然迫切想要了解孩子的学习情况。以往&#xff0c;成…

使用Provide和Inject设计Vue3插件

使用provide和inject的Vue依赖项注入非常适合构建Vue3插件或避免prop多层传递。 尽管不经常使用它&#xff0c;但是您可以仅使用两个内置方法来实现依赖项注入&#xff1a;provide和inject。 查看Composition API文档&#xff0c;在Vue 3.0中&#xff0c;使用Provide和Inject进…

深度学习:循环神经网络—RNN的原理

传统神经网络存在的问题&#xff1f; 无法训练出具有顺序的数据。模型搭建时没有考虑数据上下之间的关系。 RNN神经网络 RNN&#xff08;Recurrent Neural Network&#xff0c;循环神经网络&#xff09;是一种专门用于处理序列数据的神经网络。在处理序列输入时具有记忆性…

基于RSSI原理的蓝牙定位程序(matlab代码,3维空间、基站数量>3即可,可自适应)

目录 商品描述 商品描述 这款基于接收信号强度指示&#xff08;RSSI&#xff09;原理的蓝牙定位程序&#xff0c;专为需要高效、可靠定位解决方案的开发者和研究人员设计。无论是在室内环境还是复杂的三维空间&#xff0c;该程序都能通过N个蓝牙锚点&#xff0c;实现对未知点的…