2024程序员容器化上云之旅-第4集-Ubuntu-WSL2-Windows11版:夺取宝剑

news2024/9/29 23:35:02

故事梗概

Java程序员马意浓在互联网公司维护老旧电商后台系统。

渴望学习新技术的他在工作中无缘Docker和K8s。

他开始自学Vue3并使用SpringBoot3完成了一个前后端分离的Web应用系统,并打算将其用Docker容器化后用K8s上云。

6 夺取宝剑

🔥阅读Nigel Poulton的书,自学完Docker后,马意浓知道,前后端App,各自都要制作成docker image,先部署到本地docker compose里,之后再部署到k8s云集群里。

✅这是因为Docker提供了一个完整打包app所有依赖项的一致的环境,确保应用在开发、测试和生产环境中的行为一致。

这就能实现在测试环境中所测试的image,就是在生产环境所部署的

这是解决“在我这运行得好好的,怎么在你那不行”的问题的关键。

✅此外,将前端和后端应用容器化,需要使用等同于代码的配置文件

这种基础设施即代码的实践,能让配置的更改广而告之,配置的执行有据可查

这是解决“谁改了配置又不告诉大家?”问题的关键。如图1。


图1 Docker能提供完整打包app所有依赖项的一致的环境,以及让配置的更改广而告之,配置的执行有据可查

6.1 前后端App均部署到本地docker compose中的架构图

马意浓稍微修改了之前绘制的前后端App部署到本地Gradle/npm开发环境的架构图。

其实只是将前后端App的部署环境,都改成了docker compose。如图2。


图2 前后端App的部署环境都改成了docker compose

该如何让前后端App,都在本地docker compose里运行起来呢?

马意浓启动了Docker Desktop,并确认已经用自己的docker hub账号登录。

6.2 用gradle构建后端app并生成jar包

马意浓想要让所生成的后端app的docker image,仅包含刚好够运行的jar包,及其依赖项。

这样的docker image就能做到尽可能地小,以节省将其推送到Docker Hub的时间。

他于是决定,先用gradle命令构建后端app并生成jar包,然后再设法将其构建为docker image。

他打开一个Ubuntu终端窗口,进入项目文件夹中的infrastructure子文件夹。

接着运行命令docker compose up postgres pgadmin,启动了postgres数据库和pgadmin管理工具,为gradle构建做好了准备。

他又新打开一个Ubuntu终端窗口,进入项目文件夹中的back-end子文件夹。

他运行命令sdk use java 17.0.10-tem,设置好jdk当前版本。

之后,他运行命令./gradlew clean build,开始构建后端app。

等到屏幕出现了BUILD SUCCESSFUL字样后,他在文件夹build\\libs里,找到了刚刚生成的jar包shoppinglist-0.0.1-SNAPSHOT.jar

6.3 构建后端app的docker image

马意浓又回到了back-end文件夹。因为他知道,这个文件夹里有运行docker命令所需的Dockerfile文件。

他打算使用docker buildx build命令,因为这是对旧的docker build命令的扩展。

他从资料中发现,相比后者,前者提供了多平台构建、改进的构建缓存机制以及灵活的构建结果输出等新功能。

他输入命令docker buildx build --build-arg JAR_FILE=build/libs/shoppinglist-0.0.1-SNAPSHOT.jar -t <docker-hub-username>/shopping-list-api:v1.1.local-docker-compose .,来构建后端docker image。

(注:需要把<docker-hub-username>换成你的docker hub账号名。下同。)

他特别留心命令最后的一个不起眼的小数点没有忘记写。

因为他知道,小数点代表把当前文件夹。

这作为build命令的上下文,以找到所需的jar文件,作为构建资源。

在执行这个命令前,他又仔细检查了参数-t <docker-hub-username>/shopping-list-api:v1.1.docker-compose

他知道,-t指的是,给image加一个tag,用于标识这个image。

如果以冒号:分界,这个参数的前半段<docker-hub-username>/shopping-list-api,是这个image将来要推送到的Docker Hub上的镜像库(repository)的名称。

他觉得把后端app的docker image命名为shopping-list-api,会更加简洁。

而参数的后半段v1.1.local-docker-compose,是这个image的tag,用来标识image的这次构建的版本号。

他按下回车,执行这个命令。

等这个命令执行完,他运行命令docker image ls,验证后端app的docker image是否构建成功。

屏幕显示出新构建的image,确实带有<docker-hub-username>/shopping-list-api的repository,以及v1.1.local-docker-compose 的tag。这表明image构建成功了。

他在Docker Desktop的Images里,也看到了这个新构建的后端app的docker image。如图3。


图3 他在Docker Desktop的Images里,也看到了shopping-list-api这个新构建的后端app的docker image

6.4 在git代码库打同名的tag以对应刚刚构建的docker image版本

马意浓紧接着,运行命令git tag -a v1.1.local-docker-compose -m "v1.1.local-docker-compose",在git库里打了一个与docker image的tag同名的tag。

他知道,随着不断提交,代码库中的代码总是在不断变化。

总有一天,他推送到Docker Hub中的image会有bug。那时若想打开对应的源代码看一下,那该看git代码库中哪一次提交后的代码?

但如果他当时在构建docker image后,立即在git库里打一个同名的tag,那么就好定位代码了。

他又运行命令git push origin v1.1.local-docker-compose,把这个tag推送到远程git库中。

他接着运行命令git ls-remote --tags origin,确认这个tag已经成功推送到远程git库中了。

6.5 将后端app的docker image推送到docker hub

因为已经在Docker Desktop里登录Docker Hub了,所以马意浓直接运行命令docker push <docker-hub-username>/shopping-list-api:v1.1.local-docker-compose,将构建好的image推送到Docker hub。

等命令执行完,没有看到错误信息,他就在浏览器访问自己的Docker hub页面。

他在自己的shopping-list-api这个repository里,找到了tag是v1.1.local-docker-compose的image。这表明image推送成功。

下一步,他要构建前端app到docker image,并将其推送到docker hub。

6.6 用Dockerfile里的npm构建前端app的docker image

马意浓知道,构建前端app的docker image的过程,与后端app有些不同。

不同点就是前端app的构建命令npm run build,已经纳入前端app的Dockerfile文件里了。而不像后端app那样,构建命令在Dockerfile之外。

他运行命令进入前端文件夹front-end。

他又运行命令docker buildx build -t <docker-hub-username>/shopping-list-front-end:v1.1.local-docker-compose .,来构建前端app的docker image。

等命令执行完,他运行命令docker image ls,查看新构建的image,确实带有<docker-hub-username>/shopping-list-front-end的repository,以及v1.1.local-docker-compose 的tag。

这表明image构建成功了。

他在Docker Desktop里的Images里,也看到了这个新构建的前端app的docker image。

按理说,构建完前端app后,也应该在git代码库打同名的tag,以对应刚刚构建的docker image版本。

但他觉得从现在到上次在git库打tag这段时间,没有改代码,而且tag的名称也没变,所以他决定省略这一步。

6.7 将前端app的docker image推送到docker hub

马意浓运行命令docker push <docker-hub-username>/shopping-list-front-end:v1.1.local-docker-compose,将构建好的image推送到Docker hub。

他访问自己的Docker hub,在自己的shopping-list-front-end这个repository里,找到了tag是v1.1.local-docker-compose的image。这表明image推送成功。

6.8 在本地docker compose里运行前后端App

做足了前面的功课,马意浓知道,现在该是享受胜利果实的时候了。

因为在本地docker compose里运行前后端app的命令,超级简单。

他进入项目文件夹,然后运行命令cd infrastructure,进入这个子文件夹,

他打开docker-compose.yml文件,仔细确认了shopping-list-apishopping-list-front-endimage中配置的v1.1.local-docker-compose这样的tag,确实与之前的命令中的tag一致。

他又检查了一下docker desktop的Containers界面,发现之前为后端app打包而准备的postgres和pgadmin容器还在运行,于是他运行清理现场的命令docker compose down,将两个容器关闭并删除。

之后他运行命令docker compose up,来启动docker-compose.yml文件中配置好的那4个容器。

他特意在这个命令中,没有添加表示detach-d参数,以便观察命令执行中的输出信息是否有错误。

屏幕输出没有任何错误信息,而且最后显示Started ShoppingListApplication字样。这表示前后端App已经成功运行。

他在docker desktop里,能看到这4个容器都在正常运行。

他于是在里面用鼠标点击shopping-list-front-end-1那一行右侧的8080:8080链接,浏览器应声打开,显示了购物清单Web应用的界面。

🔥他在里面添加了一个购物项an apple。这个购物项便顺利地出现在下面的购物清单中!

他兴奋地挥拳庆贺。

至此,前后端分离的Shopping List Web App在本地docker compose里运行成功了。

6.9 清理现场

他又新打开一个Ubuntu终端窗口,进入项目文件夹中的infrastructure子文件夹,然后运行命令docker compose down

他打开docker desktop,看到Containers界面已经没有任何容器在运行了。现场清理结束。

😃马意浓很兴奋。现在前后端分离的Web应用的容器化这把宝剑,他已经拿到手里了。

接下来,他要挥剑,向k8s上云的新目标迈进。

💔但他心里隐隐有些不安。

因为对他来说,K8s云集群是个完全陌生的环境。他预感会碰到更大的障碍。

🔥【未完待续


❤️欲读系列故事的全集内容,可搜用户“程序员吾真本”,找到“2024程序员容器化上云之旅”专栏阅读。

🔥后面连载内容大纲先睹为快

🔥7 上云之路

7.1 注册Azure k8s service云平台账号

7.2 打开docker desktop kubernetes让kubectl能正常工作

🔥8 复活重生

8.1 在k8s云集群中运行shopping list web app时如何配置前端app在k8s云集群中的对外域名和端口号以解决CORS问题

8.2 在全绽园的帮助下为前端app配置ingress后解决了这个问题

8.3 在k8s云集群中的软件架构

8.4 如何新增k8s的deployment、service和ingress的配置文件,以便使用kubectl命令将ingress和postgres、shopping-list-api和shopping-list-front-end这3个微服务部署到k8s上

8.5 构建后端docker image并推送到docker hub

8.6 构建前端docker image并推送到docker hub

8.7 在k8s云集群上配置postgres、shopping-list-api和shopping-list-front-end三个微服务和ingress并运行

8.8 清理现场

🔥9 取经归来

当最终把前后端分离的web应用成功部署到azure k8s云集群上,并能顺利使用后,马意浓把整个容器化和上云之旅,写成系列文章,分享给其他程序员。


😃你能否跟着马意浓一步步做下来?在阅读中有任何疑问,欢迎在留言区留言。我会一一回复

❤️如果喜欢本文,那么点赞留言,并转发给身边有需要的朋友,就是对我的最大支持😃🤝🙏。

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

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

相关文章

【Vue3】学习watch监视:深入了解Vue3响应式系统的核心功能(下)

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

二叉树进阶oj练习

目录 1. 根据二叉树创建字符串 1&#xff09;思路 2&#xff09;代码实现 2. 二叉树前序非递归遍历实现 1&#xff09;思路&#xff1a; 2&#xff09;代码实现 3. 二叉树中序非递归遍历实现 1&#xff09;思路&#xff1a; 2&#xff09;代码实现&#xff1a; 4. 二…

Programming Abstractions in C阅读笔记:p303-p305

《Programming Abstractions in C》学习第74天&#xff0c;p303-p305总结&#xff0c;总计3页。 一、技术总结 1.时间复杂度分类(complexity classes) ClassNotationExampleconstantO(1)Returning the first element in an arraylogarithmicO(logN)Binary search in a sorte…

三菱plc控制双控电磁阀(从接线到程序)

目录 硬件设备 电磁阀的类型&#xff08;下图为例&#xff09; 三菱plc的类型&#xff08;西门子控正COOM接接正极&#xff0c;三菱控负COM接负极&#xff09; 气缸图 三菱plc与双控电磁阀接线 输出接线图&#xff08;COOM输出的公共端&#xff0c;三菱控负COM接负极&#x…

大学生课程|统计基础与python分析6|主流的评估方法:ROC曲线和KS曲线(免费下载所有课程材料)

目录 1 ROC曲线 2.查看混淆矩阵 3.实战评估股票客户流失预警模型 4.阈值的取值方法 5.KS曲线与KS值 6.获取KS值对应的阈值 7.获取KS值 对于二分类模型来说&#xff0c;主流的评估方法有ROC曲线和KS曲线两种方法 1 ROC曲线 之前已经获得了模型的准确度为79.77%&#xf…

【USENIX论文阅读】Day2

Birds of a Feather Flock Together: How Set Bias Helps to Deanonymize You via Revealed Intersection Sizes&#xff08;"物以类聚&#xff1a;集合偏差如何帮助去匿名化——通过揭示交集大小&#xff09; Xiaojie Guo, Ye Han, Zheli Liu, Ding Wang, Yan Jia, Jin L…

高级光线传播与高级外观建模

一.高级光线传播 1、无偏的 ①有偏VS无偏 蒙特卡洛估计出的结果的期望永远是对的 eg&#xff1a;PT中不管有多少样本&#xff0c;期望都是定积分的值 有偏的&#xff1a;估计出的结果的期望和积分的值不一样 一个特殊情况&#xff08;一致的&#xff09;&#xff1a;极限定…

【web APIs】1、(学习笔记)有案例!

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、概念二、使用步骤1.获取DOM对象2.操作元素内容3.属性修改3.1.常用属性修改3.2.控制样式属性3.3.操作类名(className) 操作CSS3.4.操作表单元素属性3.5.自定…

Mysql常见函数和用法(重点)

where子句中经常使用的运算符 -- 查询总分大于200分的所有同学 select * from student2 where (chineseenglishmath)>200; -- 查询math大于60 并且(and)id大于4的学生成绩 select * from student2 where math>60 and id>4; -- 查询英语成绩大于语文成绩的同学 select …

面试总结之JVM入门

文章目录 &#x1f412;个人主页&#x1f3c5;JavaEE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380;你为什么要学习JVM&#xff1f;&#x1f380;JVM的作用 &#x1f380;JVM的构成&#xff08;5大类&#xff09;&#x1f3e8;1.类加载系统&#x1f415;类什么时候会被加…

《Docker 简易速速上手小册》第2章 容器和镜像(2024 最新版)

文章目录 2.1 理解 Docker 容器2.1.1 重点基础知识2.1.2 重点案例&#xff1a;使用 Docker 运行 Python 应用2.1.3 拓展案例 1&#xff1a;Docker 中的 Flask 应用2.1.4 拓展案例 2&#xff1a;Docker 容器中的数据分析 2.2 创建与管理 Docker 镜像2.2.1 重点基础知识2.2.2 重点…

k8s(5)

目录 使用Kubeadm安装k8s集群&#xff1a; 初始化操作&#xff1a; 每台主从节点&#xff1a; 升级内核&#xff1a; 所有节点安装docker &#xff1a; 所有节点安装kubeadm&#xff0c;kubelet和kubectl&#xff1a; 修改了 kubeadm-config.yaml&#xff0c;将其传输给…

网络攻防之网络扫描

目录 1、进行ping扫描 2、进行TCP SYN扫描 3、进行TCP全连接扫描 4、进行FIN扫描 5、进行UDP扫描 6、进行操作系统扫描 7、进行主机全面扫描 8、对网络号进行扫描 环境配置拓扑图&#xff1a; 实验前准备 查看kali和靶机的ip地址信息&#xff1a; 查看两台主机是否能互…

vue中循环多个li(表格)并获取对应的ref

有种场景是这样的 <ul><li v-for"(item,index) in data" :key"index" ref"???">{{item}}</li> </ul> //key值在项目中别直接用index&#xff0c;最好用id或其它关键值const data [1,2,3,4,5,6]我想要获取每一个循环并…

数据结构知识点总结-线性表(3)-双向链表定义、循环单链表、、循环双向链表、静态链表、顺序表与链表的比较

双向链表定义 单链表结点中只有一个指向其后继的指针&#xff0c;这使得单链表只能从头结点依次顺序地向后遍历。若要访问某个结点的前驱结点&#xff08;插入、删除操作时&#xff09;&#xff0c;只能从头开始遍历&#xff0c;访问后继结点的时间复杂度为 O(1) &#xff0c; …

详解java类型转换

✨✨ 所属专栏&#xff1a; Java基石&#xff1a;深入探索Java核心基础✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; 引言 在Java编程中&#xff0c;类型转换是将一个数据类型的值转换为另一个数据类型的过程。Java中的类型转换主…

Django学习笔记-ModelForm使用(完全依赖)

1.创建模型 ,code,name,sex,entrydate 2.模型映射 python manage.py makemigrations myapp01,python manage.py migrate 3.创建模型表单,继承forms.ModelForm,Meta:元数据,models需引入,fields填写引用的模型变量 4.创建testModelForm.html,添加urls 5.views编写testmodelfo…

前端sql条件拼接js工具

因为项目原因&#xff0c;需要前端写sql&#xff0c;所以弄了一套sql条件拼接的js工具 ​ /*常量 LT : " < ", LE : " < ", GT : " > ", GE : " > ", NE : " ! ", EQ : " ", LIKE : " like &qu…

字典树入门

//本题是一道字典树的模板题 //字典树是一种高效率存储多个字符串的数据结构 //其每个结点的权值代表以该结点结尾的字符串的数量,每条边存储一个字符 //从根结点开始,按某一路径遍历到某一结点,即得到一种字符串,其个数等于当前结点存储的数值 //如从根结点开始,依次走过abc三…

【iOS ARKit】ARWorldMap

ARWorldMap 用于存储 ARSession 检测扫描到的空间信息数据&#xff0c;包括地标&#xff08;Landmark&#xff09;、特征点&#xff08;Feature Point&#xff09;、平面&#xff08;Plane&#xff09;等&#xff0c;以及使用者的操作信息&#xff0c;如使用者添加的 ARAnchor …