MHBlog项目部署记录
本篇随笔记录了在学习完SGBlog这个项目之后将这个项目作为我第一个完成的项目部署到云服务器的过程.
虽说之前有了解并且看过相关的视频教学,但是第一次实践还是出现了很多问题
选择服务器
服务器我在这里选择的是阿里云的云服务器ECS,为什么要选择阿里云呢? 因为我的OSS也是阿里云的,所以想着要用就用同一家的吧
因为我有学生认证,所以阿里云有3个月的试用云服务器,这里我就选用了2核2G的最便宜一档的服务器 (因为不是什么很大的项目而且估计也没什么人看)
在选择完服务器的配置之后来到了选择系统这一步,在选择系统的时候其实我一开始是选择的windows,心想着windows的图形化界面用起来很舒服,而且我也熟悉这个系统,随后安装了Windows系统来作为我的云服务器系统.
服务器启动之后想着如何连接到云服务器呢?其实之前学习Docker的时候我用的是腾讯的云服务器,那时候使用的Linux系统,所以我使用的是WindTerm来创建SSH会话,但是我看阿里云竟然有自己的一个客户端,如图
这个客户端能快速远程访问桌面,很满意
在使用windows的途中我想起来当初Docker也是运行在Linux上,虽说Windows都能办到这些(因为我就是这个环境解决了这些问题),但是我不想在云服务器上浪费太多时间,之后便切换到了Linux里的CentOS系统.
项目打包
先说前端项目吧,很简单,客户端使用build构建dist,管理端使用build:prod构建dist,因为两者虽是Vue,但是开发的框架不太一样 (不想细说了,放过我吧)
之后就是SpringBoot工程的打包,其实第一次打包的时候就是简单的使用Maven工具里的Install打包的,jar包运行的时候显示了报错 xxxxx-0.0.1-SNAPSHOT.jar中没有主清单属性,原因是不能找到程序的主类,需要修改父pom文件和子模块minghai-blog的pom文件和子模块minghai-admin的pom文件
<!-- 此插件必须放在父 POM 中 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<executions>
<!--
执行本插件的方法为,在主目录下执行如下命令:
mvn package assembly:single
对于 IntelliJ IDEA,生成的 JAR 包位于每个模块下的文件夹 target
-->
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<!-- 此处 IntelliJ IDEA 可能会报红,这是正常现象 -->
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<!-- 配置程序运行入口所在的类 -->
<mainClass>com.minghai.BlogAdminApplication</mainClass>
</manifest>
<manifest>
<!-- 配置程序运行入口所在的类 -->
<mainClass>com.minghai.MHBlogApplication</mainClass>
</manifest>
</archive>
<!-- 设置 JAR 包输出目录 -->
<outputDirectory>${project.build.directory}/#maven-assembly-plugin</outputDirectory>
<!-- 设置打包后的 JAR 包的目录结构为默认 -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
子模块的pom文件
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<finalName>${project.artifactId}</finalName>
</build>
两个项目打包之后将用户端管理端的jar包复制到一个文件里jar放两个不同的位置
这里要先测试以下我们的jar包能否正常运行
在jar包的目录输入java -jar <包名>.jar
出现以下的画面就是SpringBoot的jar包启动成功了.
前端则是用Nginx来部署项目,这里将两个dist放入前端的html文件夹进行测试,并且修改config文件,这里就不细展开讲(因为windows的nginx部署跟linux的有一点点不一样(至少我是这么觉得的))
docker镜像的制作
开始痛苦了
这里我在我的Windows系统上安装了Docker Desktop,期间经历了Docker Engine Stopped等各种麻烦(最后妥协了将Docker Desktop安装在了C盘,主要是不想麻烦了),为什么要在Windows上安装Docker? 因为在这上面制作镜像,超!级!方!便!
接下来就将需要制作成一个镜像的文件放在同一目录下以下是Dockerfile的内容(其实可以不放,但是还是放上来看看)
- 管理端的镜像文件
- 用户端的镜像文件
- Nginx前端文件的镜像文件
可以看到这里是暴露了三个端口,8093的是用户端的,81的则是管理端的,80是Nginx默认自带的页面(其实可以不用带这个,主要是我想留着测试)
制作镜像时出现的坑
- 在做到一半的时候我突然想起来我这里后端项目用的都是开发的时候的环境,也就是我并没有将数据库地址什么的写成我服务器的地址,也就是说我服务器里的Mysql容器和Redis容器暴露出的端口我这个后端项目并不会连接所以启动的时候Mybatis和Redis都会报错(数据源出问题了)
- 因为SpringBoot的application是可以外部配置的,在同一目录下的application文件能修改内部的,所以我这里就创建了一个application.yml文件来修改数据源的一些参数
(具体就不给看了吧,毕竟是服务器的地址和端口,还有数据库的账号密码) - 其实有想过挂载卷到容器上的application上的,但是想想太麻烦了,而且这个也不是什么需要持久化的东西,所以就直接在镜像里打包了.
- Nginx的default.conf和nginx.conf是合并的配置文件(目前是这么理解的)而我直接在Windows上测试完成直接将Nginx.config里的内容copy到了default.conf里的,所以导致docker后来部署的时候老是报错这一行代码不能出现在这里之类的错误.
在云服务器的Linux CentOS系统上使用Docker进行项目的快速部署
一点都不快速,纯命令行的系统快折磨死我了
(其实是第一次部署什么都不熟悉老是出错误而已)
- 通过阿里云的这个SSH连接进入到CentOS系统里(其实还有windTerm,但我觉得阿里云这个更好用),查阅Docker的文档使用指令安装完Docker之后检查Docker安装情况没问题之后开始拉取制作好的镜像进行部署
- 这里因为Docker被墙了(2024/10/24)所以在没有科学的情况下无法正常拉取到镜像,这时后我们就需要给Docker添加镜像
- 这里我就不上服务器来截图了,就拿我的虚拟机CentOS系统来说明,我们进入/etc/docker这个目录,在里面找到daemon.json这个文件,我们打开这个文件并将我们找到的镜像加入到这里面
sudo nano /etc/docker/daemon.json
{
"registry-mirrors": [
"https://1thrb1uh.mirror.aliyuncs.com",
"https://dockerpull.com",
"https://docker.udayun.com",
"https://dockerproxy.cn",
"https://docker.rainbond.cc",
"https://docker.211678.top"
]
}
- 需要注意的一点是内容必须是Json格式,出一点错启动Docker的时候都会报错
- 但是这个方法我自己使用下来有个问题,那就是只能pull,其他的操作都不行(search,login,(push没试过))
- 解决方法:Linux上的科学
- 其实在这个阶段卡最久的就是我的容器各种启动失败报错,其中最多的就是配置文件(包括不限于上文提到的nginx配置文件跟windows系统的区别以及后端文件数据库参数修改的问题)的问题,通过百度一个个问题之后也是能解决.
- 这个阶段主要是复习了很多Docker的知识和Linux系统的知识
- 还有一点就是在这里我的Mysql是使用挂载卷来实现数据持久化的保存在了/mydata/mysql目录里
- 这里要记住一个很重要的参数就是 -v <你的目录>:<容器中的目录>将容器中的目录绑定到挂载卷里,这样子就算容器删除了下次添加容器的时候也是能读取到这个数据的
- redis里记得将daemonize设置成no,不然会闪退
(我也没去研究为什么)
项目的正式上线
- 在上线之后我进入前端,发现能访问了,非常好!
- 但是在点开一篇文章之后我傻眼了,弹出了后端接口404,我去查看了我的容器运行状况,
docker ps
- 发现容器都在正常的运行,我查看了用户端后台的日志
docker logs <容器名字>
- 发现我这个程序没!有!收!到!任!何!请!求!
- 打开F12一看,好家伙,请求地址localhost:7777,这是还没把前端文件里的baseUrl改过来,于是去前端里更改了baseUrl之后重新打包上传部署
- 之后就没问题了,可以正常使用功能,项目也算是上线了(有Bug但是不是很严重所以就不想着去解决了,主要是这个系统是我的第一个从后端开发正式部署上线的项目)
这个项目之后的感想
- 其实这个项目整体难度并没有这个大,对我来说最难的是实现登录验证的SpringBootSecurity和Jwt的使用(因为在项目前几天的时候我还在想前后端项目分离了之后我还怎么保存登录状态,之前的Servlet和Jsp又或者是SpringMvc使用模板引擎都是使用Session来保存登录状态),SpringSecurity还提供了权限控制,更是方便.
- 果然学会一样东西最好的方式就是动手实践,因为当初这个docker的使用我看视频过了一遍感觉似懂非懂,很多都是模模糊糊的过去了,所以这次部署项目的时候就是对docker有个大概印象但是还是要去查阅大量的文档教程来使用
- 在这个项目中加深了对MVC软件设计模式的理解,复习了SpringMVC,Spring,Mybatis(MybatisPlus)的使用(其实说白了就是加深巩固了SSM整合开发框架)
- 这个项目还带我接触了OSS对象存储和云服务器的实战部署,使用了linux来部署项目(之前没怎么接触过,最早解除是在学嵌入式C++开发的时候)
- 感谢三更老师的课程!