Appearance
项目部署上线
前言
为了能让用户通过线上地址预览项目,我们需要将本次编写的前后端项目部署到服务器上。本章节为大家带来部署 Node
服务端项目和前端项目。
知识点
- CentOS 服务器
- 配置 ssh
- MySQL 服务器端安装
- egg 服务端部署
- pm2 进程守护
代码都已经推到 Github
仓库,地址如下所示:
记账本服务端代码仓库地址:https://github.com/Nick930826/jue-diary-server
记账本前端代码仓库地址:https://github.com/Nick930826/juejue-vite-h5
正文
购买服务器
我们先从服务器的购买谈起,如果已经购买服务器的同学,可以省略这一步的。
为什么要购买服务器呢,当你本地开发好项目的时候,你只能跑在你的本机电脑上,所以此时你只能独自欣赏自己的项目。别人无法通过访问你的 IP 地址,去浏览你跑在本地的项目。而服务器的能力,就是可以让你把项目跑在服务器上,让用户通过访问你的服务器抛出的IP
+ 端口号
,去浏览你的网页或者使用你抛出的接口。
服务器的品类也有很多,阿里云、腾讯云、华为云、七牛云等等,都有提供云服务器的功能,这里我选择的是阿里云服务器,同学们可以自行选择。我选择阿里云的原因很简单,它的用户较多,遇到问题的话,网上会有比较多的解决方案,少走弯路。
购买服务器有两种选择,第一种是「包年包月」,有条件的同学可以选择包年,既然接触了全栈开发,或多或少都需要跟服务器打交道;第二种则是「按量收费」,按量收费的特点是可以根据自己的需要,开启或关闭服务器。
购买时,注意一点,一定要选择 CentOS
的镜像,版本尽量选择最高版本。因为它是基于 unix
,对开发比较友好。
这是我购买的配置,如下所示:
用于平时部署简单项目,这样的配置基本上是满足的。但是如果你要运行一些比较大型的项目,并且有多个的话,2G
的内存是不够的,因为考虑到项目会在服务器端进行打包,会占用不少内存,有可能会因为服务器的内存不足,而导致打包失败,到时候再升级内存的话,就会比较费钱。
ssh 配置
购买服务器之后,首先要做的就是登录服务器,市面上不乏可视化的服务器造作软件,但我的建议是指令操作才是一个程序员应该具备的能力。
在此之前,我们先在本地配置好 ssh
。
什么是 ssh
百度百科给出的定义:
SSH 为 Secure Shell 的缩写,由 IETF 的网络小组(Network Working Group)所制定;SSH 为建立在应用层基础上的安全协议。SSH 是较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。SSH最初是UNIX系统上的一个程序,后来又迅速扩展到其他操作平台。SSH在正确使用时可弥补网络中的漏洞。SSH客户端适用于多种平台。几乎所有UNIX平台—包括HP-UX、Linux、AIX、Solaris、Digital UNIX、Irix,以及其他平台,都可运行SSH。
我用一句话概括它:
SSH是一种网络协议,用于计算机之间的加密登录。
服务器也是一台计算机,只不过它是远端的计算机,大家买的阿里云、腾讯云等服务器,相当于一台常年开启状态的计算机,可以通过 dos
界面进行操作,也可以通过市面上的服务器可视化工具进行管理。
本地安装 ssh,实现免密登录
如果已经安装过,忽略这部分的内容,没有安装的请继续往下看。
如果开发机器是 Windows
系统,可以先在本地安装好 git
,然后通过命令行来到项目的 ~
路径下,运行如下指令生成 ssh key:
bash
ssh-keygen -t rsa -C "xxxxx@xxxxx.com"
上述邮箱地址写邮箱地址,这里不一定要写邮箱,只是为了方便找到生成的 ssh key
是谁的。
执行完成后,前往 ~/.ssh
路径下,查看是否生成好的相应的公钥。笔者的公钥如下所示:
id_rsa.pub
文件里面的内容,就是需要的公钥内容。
拿到本机的公钥之后,进入阿里云服务器,同样先看看服务器是否有设置好公钥,打开 ~/.ssh
查看。如果是刚买的服务器,建议先全局安装好 git
,然后再去查看 ~/.ssh
,正常情况下是如下所示:
如果没有内容,建议按照本地配置 ssh key 的方法,在服务器端再做一次配置。
上图所示的 authorized_keys
文件,便是设置免密登录的配置文件。只需将你本地电脑的 id_rsa.pub
公钥内容,拷贝到 authorized_keys
中并保存,那么你便可以在本地远程免密登录服务器,如下所示:
如果没有配置好 authorized_keys
,那么你每次做上述操作的时候,都会提示你输入服务器的登录密码。这样就会阻碍我们后续通过 pm2
远程自动化登录服务器。
既然已经配置好了服务器的 ssh
,我们将服务器的公钥 id_rsa.pub
,拷贝到我们存放代码仓库的权限配置里,这一步的目的是让服务器可以通过 ssh
的方式拉取代码仓库内的最新代码,配置如下:
笔者将代码放到了 Github
仓库,上图为 Github
的 Setting
界面,点击 SSH and GPG keys
,新建一个 SSH key
,将服务器的公钥粘贴进去,完成之后,你便可以在服务器通过 ssh
的方式拉取代码。
以上操作是对本地计算机和云端服务器的一些基础配置,目的是为后面的操作打下基础。
MySQL 服务器端安装
第三章笔者讲述了 MySQL
在本地的安装,因为那时我们开发也是在本地,所以配置一个本地数据库足矣。而此时,我们需要将服务端的项目上线,Egg
开发的项目就不能再连接本地数据库,当然,线上服务代码也连接不上我们本地的数据库。
第一步
远程登录服务器之后运行以下命令更新 yum
源:
bash
rpm -Uvh http://dev.mysql.com/get/mysql57-community-release-el7-9.noarch.rpm
这里我们使用的
MySQL
版本是 5.7.28。
安装 MySQL
,注意这里安装稳定社群版:
bash
yum install mysql-community-server
全部安装完成之后,可以通过以下命令查看是否安装成功:
bash
[root@iZbp15axph2ymmv3k3i5oxZ ~]# mysql --version
mysql Ver 14.14 Distrib 5.7.28, for Linux (x86_64) using EditLine wrapper
第二步
此时需要配置一下安装好后的 MySQL
。执行如下命令启动它:
bash
systemctl start mysqld
设置开机自动启动:
bash
systemctl enable mysqld
如果遇到一些问题,需要重启数据库的话,执行以下指令:
bash
systemctl restart mysqld
网上说通过以下命令可以看到初始化密码,因为为了安全考虑,5.7 以后的 MySQL
版本,都会有一个默认的初始密码,可以通过下列指令来获取:
bash
grep 'temporary password' /var/log/mysqld.log
如果你通过这条命令行能获取到初始密码,那基本上你就可以进入 MySQL
数据库,重制你的密码了。但是我碰到的情况是,mysqld.log
文件为空,没有内容。
于是经过翻阅资料,查到可以设置一些配置,跳过输入密码然后进入 MySQL
数据库。操作如下:
1、修改 MySQL
的配置文件(默认为/etc/my.cnf),在[mysqld]
下添加一行skip-grant-tables
,如下:
bash
[mysqld]
skip-grant-tables
2、保存配置文件后,重启 MySQL
服务 systemctl restart mysqld
。
3、执行 mysql \-u root \-p
登录 MySQL
,然后不输入密码直接回车。
4、登录之后,修改密码,操作如下:
bash
update mysql.user set authentication_string=password('123456') where user='root'
5、记得去阿里云服务 ESC
实例的安全组里把 3306
端口开启,因为 MySQL
启动之后,默认是跑在 3306
端口上的。
上述一系列操作的目的,就是将 MySQL
在服务器内成功安装,并且启动。这样我们便可以通过 ip+端口
的形式,在本地通过 DBeaver
远程连接服务器端的数据库,下面是连接操作:
服务器地址:笔者的地址是
47.99.134.126
,这里可以填写你们自己的地址。端口:默认是
3306
。用户名:默认是
root
。密码:这里的密码就是上述我们安装
MySQL
时,自己设置的密码。
填写完之后,点击底部的确认按钮,便可连接到服务器的 MySQL
,如下所示:
上图所示,笔者已经在服务器端建好了 jue-cost
表,ER图
如上所示。
这里提供给大家一个 SQL
文件,可以直接在数据库导入 SQL
文件,直接创建好需要的表结构。
SQL文件下载:jue-cost。
新建好一个数据库之后,右键选择导入上述文件即可。当然,你也可以手动新建一个数据库,并在数据库内创建这三张表,可以参照第五章讲述的内容。
部署服务端代码
接下来我们要做两件事情,第一步先将本地的服务端代码上传到代码仓库,Github
和 Gitee
都可以,只要是一个线上管理的代码仓库便可。这样做的目的是便于后续的代码更新,可以在服务器及时地拉取到最新的代码。
笔者已经将服务端代码上传到了 Github
,地址如下:
这里要注意的是,在 /config/config.default.js
文件中,你需要修改你自己的数据库名和密码,如下:
javascript
exports.mysql = {
// 单数据库信息配置
client: {
// host
host: 'localhost',
// 端口号
port: '',
// 用户名
user: 'root',
// 密码
password: '你自己的数据库密码',
// 数据库名
database: '你自己新建的数据库名称',
},
// 是否加载到 app 上,默认开启
app: true,
// 是否加载到 agent 上,默认关闭
agent: false,
};
我们前往服务器拉取最新的服务端代码,如下所示:
拉取完成之后,查看文件夹,会多处这么一个项目:
进入项目,安装 node_modules
包,如下所示:
安装完成之后,执行 npm run start
,服务端项目就启动完成了,不用担心它会挂掉,Egg
自带进程守护功能。
于是乎,项目就被运行在这样一个地址上:
我们不妨测试以下获取用户信息接口是否能连通,如下所示:
目前我们尚未登录,请求时没有携带 token
,所以此接口返回了 token
不存在的错误信息。
这就表明,服务端部署已经成功,你可以通过该接口地址去访问相应的接口,来制作前端页面。
前端 pm2 部署
服务端项目部署完之后,我们继续部署前端项目。先来描述一下前端项目从打包到部署到服务器上的整个过程。
1、首先我们需要运行 npm run build
对项目进行打包操作,打完包后,在根目录会出现一个 dist
目录,如下所示:
如上图所示:
assets:存放打包后的静态资源,如 js、css、图片等。
index.html:项目入口页面,就是整个项目需要通过这个页面初始化,内部也看到了引入了 index.xxx.js,这是整个项目的 js 脚本。
现在需要想方设法让 index.html
跑在服务器上的某个端口。
这里,为大家推荐一个比较好用的一个插件,通过命令行安装它:
bash
npm i pushstate-server
pushstate-server
为什么提供了很便捷的启动 web
服务的配置,内部的原理是通过 connect
服务器,开启一个端口,将 dist/index.html
文件作为静态模板输出。
安装好之后,在 H5
项目的根目录添加 juejue-vite-h5-server
文件,内容如下:
javascript
const server = require('pushstate-server')
server.start({
port: 5021,
directory: './dist'
})
port:需要启动的端口号。
directory:
index.html
所在的目录路径,这里直接写相对路径就好。
配置好上述内容之后,就需要引入 pm2
的概念,它是一个进程管理工具,对于前端而言最重要的功能便是进程守护,通过它启动的 node
服务,服务挂了会自动拉起项目。
在 H5
项目根目录新增 ecosystem.config.js
,在项目本地执行 pm2
的时候,会匹配的项目根目录下的 ecosystem.config.js
文件,并且执行它的配置。配置如下:
javascript
module.exports = {
apps: [
{
name: 'juejue-vite-h5',
script: 'juejue-vite-h5-server.js'
},
],
deploy: {
production: {
user: 'root',
host: '47.99.134.126',
ref: 'origin/master',
repo: 'git@git.zhlh6.cn:Nick930826/juejue-vite-h5.git',
path: '/workspace/juejue-vite-h5',
'post-deploy': 'git reset --hard && git checkout master && git pull && npm i --production=false && npm run build:release && pm2 startOrReload ecosystem.config.js', // -production=false 下载全量包
env: {
NODE_ENV: 'production'
}
}
}
}
apps:
script
为服务器通过pm2
要执行的脚本,name
为脚本在pm2
列表中的名称,这个名称要注意,避免后续其他项目重名,在服务器中你会无法区分是哪个项目。deploy:
production
为部署正式环境的配置,这里我就不配置beta
环境的代码,因为目前就只有一台服务器。production.user:默认 root 用户。
production.host:要部署的服务器
IP
地址。production.ref:要部署的代码,在代码仓库中的哪个分之,如果是测试环境,那么这里应该就是
origin/develop
,这里我们默认是正式。production.repo:代码存放的地址,这里是我的地址,你可以写你自己的代码仓库地址。
production.path:在服务器拉取远程仓库地址之后,存放在服务器中的地址,这里我习惯存放在
workspace
文件夹内,同学们可以根据自己的习惯进行操作。production.post-deploy:需要执行的一些指令,如
git reset
重制、git checkout master
切换分支、git pull
拉取最新代码、npm i
安装依赖、npm run build
打包构建、pm2 startOrReload ecosystem.config.js
pm2 执行项目。
这里有一点要注意的是,安装依赖的时候,设置
--production=false
的目的是将devDependencies
中的包也进行安装,否则我们无法进行vite
打包操作。
首次执行的时候,由于服务器中并没有 juejue-vite-h5
这个项目,所以我们需要初始化一下项目,如下所示:
bash
pm2 deploy ecosystem.config.js production setup
执行上述代码之前,服务器并没有 juejue-vite-h5
项目:
我们尝试在前端项目中执行上诉指令:
成功之后,查看服务器中是否拉取成功:
此时服务器中已经存在 juejue-vite-h5
项目,接下来就是自动化执行整个部署流程,执行指令:
pm2 deploy production
注意,代码一定要先提交,因为服务器需要拉取最新的代码,这里必须要保持本地 commit 是没有未提交的。
上述方式如果是服务器的内存是够的情况下,可以正常自动化部署,但是笔者的服务器跑了太多的项目。导致在服务器执行打包操作的时候,内存不足,将部署进程杀死了。
于是我采用本地将项目打包好,连同 dist
一起上传到仓库,服务器在拉取代码的时候就不用再执行打包操作,直接执行 pm2 startOrReload ecosystem.config.js
操作。所以我们需要修改 ecosystem.config.js
如下:
javascript
'post-deploy': 'git reset --hard && git checkout master && git pull && npm i --production=false && pm2 startOrReload ecosystem.config.js', //
再次执行 pm2 deploy production
,如下所示:
部署成功之后,笔者的前端项目是部署在 5021
端口上的,所以直接访问 http://47.99.134.126:5021
,如下所示表示成功部署:
恭喜你,你已经成功将前端项目通过 pm2
部署到服务器,并且正常运行了。后续的更新操作,你可以直接将代码在本地打包完,推到代码仓库后,在项目下运行 pm2 deploy production
就能自动部署到服务器。
总结
部署项目的配置过程可能非常艰辛,但是做程序很多时候就是这样,这种方式部署项目的付出回报率是很可观的,你不必再每次打包之后,将项目压缩拖到服务器,而是通过一条简单的指令,一键部署到服务器,大大提高了工作效率。
如果有条件的同学,使用的是 GitLab
作为代码仓库,还可以通过 CI、CD
进行持续集成,这里不展开分析。