NuxtJS项目本地部署和自动化部署

本章节以realworld-nuxtjs项目为例,将项目部署在ucloud服务器上,主要学习项目的最简单的部署方式、使用PM2启动Node服务、自动化部署方式,以及在部署过程中遇到的问题和解决方案。

项目打包

项目部署的前提是打包,Nuxt.js 提供了一系列常用的命令, 用于开发或发布部署

命令 描述
nuxt 启动一个热加载的 Web 服务器(开发模式) localhost:3000
nuxt build 利用 webpack 编译应用,压缩 JS 和 CSS 资源(发布用)
nuxt start 以生产模式启动一个 Web 服务器 (需要先执行nuxt build)
nuxt generate 编译应用,并依据路由配置生成对应的 HTML 文件 (用于静态站点的部署)

可以将这些命令添加至 package.json

1
2
3
4
5
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start"
},

这样可以通过 npm run <command> 来执行相应的命令。如:npm run dev表示以开发模式启动带热加载特性的 Nuxt 服务。

提示: 要将参数传递给 npm 命令,您需要一个额外的--脚本名称(例如:npm run dev --参数 --spa)

执行 npm run build 打包项目,打包后的文件存放在 .nuxt/dist

dist

最简单的部署方式

配置 Host + Post

nuxt.config.js

1
2
3
4
5
6
7
module.exports = {
server: {
// 设置成 0.0.0.0 监听所有的网卡地址
host: '0.0.0.0', // 访问地址 default localhost
port: 3000 // 端口号 port
},
}

压缩发布包

把下面图中标识的文件,进行压缩(realworld-nuxtjs.zip)
命令

  • .nuxt:Nuxt打包生成的资源文件
  • static:项目静态资源
  • nuxt.config.js:提供给Nuxt服务
  • package.json:用于服务端第三方包的安装
  • package-lock.json:用于服务端第三方包的安装

把发布包传到服务端

  1. 查看服务器IP地址:(ucloud服务器为例)
    命令

  2. 连接服务器(cmd 命令行、XShell、git …)

    1
    $ ssh root@106.75.181.60  # ssh root@公网IP

    命令

  3. 在服务器中创建realworld-nuxtjs文件,将打包后压缩的文件realworld-nuxtjs.zip传递到服务器中
  • 创建文件夹,并进入文件夹,查看当前文件的路径

    1
    2
    3
    4
    5
    $ mkdir realworld-nuxtjs
    $ cd realworld-nuxtjs/

    # 查看当前的目录路径path
    $ pwd

    命令

  • 执行 exit 命令退出服务器,或者新开一个 cmd 窗口,将压缩包上传到服务器

    1
    2
    # scp realworld-nuxtjs.zip root@xxx.xxx.xxx.xxx:path
    $ scp realworld-nuxtjs.zip root@106.75.181.60:/root/realworld-nuxtjs

命令

解压

  • 重新连接服务器,并进入压缩包存放的目录,进行解压

    1
    2
    3
    $ ssh root@106.75.181.60
    $ cd realworld-nuxtjs/
    $ unzip realworld-nuxtjs.zip
  • 查看解压后的文件,-a 表示查看全部(包括隐藏目录)

    1
    $ ls -a

安装依赖

1
npm i

安装成功后如图所示:
命令

需要注意:如果没有安装 node,先要在服务器上安装 node,否则会报错,详情查看服务器端node安装章节

启动服务

1
npm run start

命令

使用http://106.75.181.60:3000/(公网IP:端口号)在浏览器中查看部署成功项目如下所示:
命令

当在浏览器中访问106.75.181.60:3000报如下错误时候,表明3000端口并未开放,需要在服务器中开放 3000 端口
命令

具体操作步骤查看下面的UCloud服务器防火墙设置部分

服务器端node安装

使用自己封装的脚本安装

封装脚本和下载的安装包查看:node和pm2安装包

服务器端上传文件执行脚本,安装成功后测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 新建nodejs目录用于存放安装包
$ mkdir nodejs

# 安装包压缩上传至服务器
$ scp nodejs.zip root@106.75.181.60:/root/nodejs

# 解压
$ unzip nodejs.zip

# run.sh文件增加可执行权限
$ chmod +x run.sh

# 执行run.sh安装node和pm2
$ sudo ./run.sh

# 检查: 输入 pm2 看是否有输出
$ pm2
# 检查:输入 node -v 看是否有结果
$ node -v
# 检查:输入 npm -v 看是否有结果
$ npm -v
#### end install ####

使用命令安装

参考 云服务器 ECS(CentOS) 安装 Node

UCloud服务器防火墙设置

防火墙设置两个地方:

  • 外网防火墙 (通过服务器厂商提供的页面进行设置 )
  • 服务器内部防火墙服务配置 ( 通过服务器命令行 )

外网防火墙

  • 登录 官网
    命令

  • 新建防火墙规则组
    命令

  • 通过复制已有规则新建
    命令
    命令

  • 编辑新防火墙规则
    命令

  • 添加具体新规则
    命令

    前端项目喜欢用 3000 端口, 要用哪个端口就仿照这个操作即可
    命令

  • 给服务器设置新防火墙规则
    命令
    命令

内部设置

依次执行下面指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1.查看防火墙状态
systemctl status firewalld.service

# 2.开启防火墙
systemctl start firewalld.service

# 3.开放3000端口
firewall-cmd --zone=public --add-port=3000/tcp --permanent

# 4.重启防火墙使新设置生效
firewall-cmd --reload

# 5.查看已经打开放的端口
firewall-cmd --list-ports

命令

服务器内部防火墙服务配置

使用PM2启动Node服务

PM2 是什么?

刚才我们在服务端是直接通过npm run start命令来启动了Web服务,如果我们通过这种方式启动起来以后,此时占用了命令行。我们希望它在后台运行这个应用,因此就需要用到pm2工具。

PM2 是一个带有负载均衡功能的 Node 应用进程管理器。

使用 PM2 启动服务

1
2
# ln -s pm2 二进制执行文件所在路径 /usr/local/bin(建立软连接的路径--环境变量)
$ ln -s /usr/local/node-v14.16.0-linux-x64/bin/pm2 /usr/local/bin
  • 进入项目所在目录,使用命令启动服务
1
2
$ pm2 start npm --start 
# pm2 start 脚本路径

pm2 start npm --start相当于给npm传参start,通过npm启动服务,服务被pm2进行管理

启动成功后如下图所示:
命令

  • 关闭 pm2
1
2
3
4
pm2 stop id 
# 或
pm2 stop name
# pm2 stop npm

运行结果如下图所示:
命令

启动成功后使用http://106.75.181.60:3000/(公网IP:端口号)在浏览器中查看

pm2 常用的命令

命令 说明
pm2 list 查看应用列表
pm2 start 启动应用
pm2 stop 停止应用
pm2 reload 重载应用(保证在进程激活的状态下一个一个重启)
pm2 restart 重启应用(修改文件后重启)
pm2 delete 删除应用
pm2 kill 服务退出(关闭全部进程)

自动化部署

传统的部署方式需要反复地更新、构建、发布,显得很麻烦。我们希望这件事情能够自动化,即使用现代化的部署方式(CI/CD)
命令

CI/CD 服务

  • Jenkins
  • Gitlab CI
  • GitHub Actions
  • Travis CI
  • Circle CI

GitHub Actions 自动部署

环境准备

  • Linux 服务器
  • 把代码提交到 GitHub 远程仓库

配置 GitHub Access Token

https://github.com/settings/tokens

  • 登录 GitHub,点击图像,选择 Settings,点击 Developer settings,如图所示:
    命令

  • 然后,选择 Personal access tokens,点击Generate new token,创建Token,如图所示:
    命令

  • 填写生成 Token 的相关信息,以及选择相关权限,点击最下面Generate token按钮来生成Token,如图所示:
    命令
    生成的Token记得复制一份,因为页面刷新后就看不到具体的值
    命令

  • 最终生成Token,如图所示:
    命令

  • 配置到项目的 Secrets 中:项目所在的 GitHub 地址realworld-nuxtjs
    进入仓库,选择 settings,点击 Secrets,再点击 New repository secret,填入生成的TOKEN,如图所示:

    命令

配置 GitHub Actions 执行脚本

  • 在项目根目录创建 .github/workflows/main.yml 目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
name: Publish And Deploy Demo
on:
push:
tags:
- 'v*' # 提交 以 v 开头的命令时,才会触发自动部署

jobs:
build-and-deploy:
# 运行环境
runs-on: ubuntu-latest
steps:

# 下载源码
- name: Checkout
uses: actions/checkout@master

# 打包构建
- name: Build
uses: actions/setup-node@master
- run: npm install
- run: npm run build
- run: tar -zcvf release.tgz .nuxt static nuxt.config.js package.json package-lock.json pm2.config.json

# 发布 Release
- name: Create Release
id: create_release
uses: actions/create-release@master
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }} # TOKEN 对应我们添加的 secret name
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false

# 上传构建结果到 Release
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@master
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}
with:
# 上传地址
upload_url: ${{ steps.create_release.outputs.upload_url }}
# 上传文件
asset_path: ./release.tgz
# 上传之后的文件名
asset_name: release.tgz
asset_content_type: application/x-tgz

# 部署到服务器
- name: Deploy
uses: appleboy/ssh-action@master
with:
# 连接远程服务的信息(Secrets 中,配置下面属性)
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
port: ${{ secrets.PORT }}
# 运行在远程服务器中
script: |
cd /root/realworld-nuxtjs # 远程服务器的web目录
wget https://github.com/Eline302/realworld-nuxtjs/releases/latest/download/release.tgz -O release.tgz # 下载上传的发布包到服务器(将Eline302/realworld-nuxtjs改为自己项目所在的远程仓库地址)
tar zxvf release.tgz # 解压
npm install --production # 安装生产依赖
pm2 reload pm2.config.json # 启动服务
  • 将所需用到的 HOST 、PORT、USERNAME、PASSWORD ,配置到 Secrets 中,和添加TOKEN方式一样
    命令

  • 配置 PM2 配置文件

根目录下,新建 pm2.config.json

1
2
3
4
5
6
7
8
9
{
"apps": [
{
"name": "RealWorld",
"script": "npm",
"args": "start"
}
]
}
  • 提交更新
1
2
3
4
5
6
7
8
9
10
11
12
$ git add .

$ git commit -m "发布部署-测试"

# 新建标签 git tag 版本号
$ git tag v0.1.0

# 查看创建的tag
$ git tag

# 将代码推送到对应的远程tag中
$ git push origin v0.1.0

提交成功后如下图所示
命令
在项目仓库中也可以看到
命令

  • 查看自动部署状态

1.登录 GitHub,查看新建的 tag:
命令

2.点击 actions ,在All workflows中可以看到部署的版本,如图所示:
命令
3.部署成功,如图所示:
命令

使用http://106.75.181.60:3000/(公网IP:端口号)在浏览器中查看

在部署过程中可能会使用的其他命令

创建文件与删除文件

命令 说明
mkdir test 建立新的目录
rmdir test 删除已建立的目录(只能删除空文件夹)
rm -rf test 删除非空的文件夹

scp相关命令

scp命令可以实现本地与远程服务器之间的双向传输,本地文件可以传输到远程服务,也可以把远程服务器上的文件传输到本地,而且是加密的。

scp [options] source dest

  • 从服务器上下载文件
    scp username@servername:/path/filename /var/www/local_dir(本地目录)
1
$ scp root@xx.xx.xx.xx:/var/test.txt /var/www/local_dir
  • 上传本地文件到服务器
    scp /path/filename username@servername:/path
1
$ scp /var/www/test.html  root@xx.xx.xx.xx:/var/www/
  • 从服务器下载整个目录
    scp -r username@servername:/var/www/remote_dir(远程目录) /var/www/local_dir(本地目录)
1
$ scp -r -P 2333 root@xx.xx.xx.xx:/var/www/test /var/www/ /var/www/local_dir
  • 上传本地文件到服务器
    scp -r local_dir username@servername:remote_dir
1
$ scp -r test.html  root@xx.xx.xx.xx:/var/www/
  • 指定密钥文件

这里指定了密钥文件id_rsa.1做为ssh的连接参数,不使用默认的密钥文件。

1
$ scp test.txt root@xx.xx.xx.xx:/home/ -i ~/.ssh/id_rsa.1
  • scp命令常用的参数有三个:
    -P 是端口号 放在 scp后面
1
2
3
4
5
6
7
-P 数据传输默认端口,默认是22
-r 递归拷贝整个目录
-i 指定密钥文件,参数直接传递给ssh使用
-l 限定网速,以Kbit/s为单位
-C 允许压缩
-1,-2 强制scp命令使用ssh1或者ssh2协议
-4,-6 使用ipv4或者ipv6寻址

github中删除 release/tag

找到本地目录下

  • 创建 tag
1
2
git tag [tag]
git push origin [tag]
  • 删除 tag
1
2
git tag -d [tag]
git push origin :[tag]

参考

【Linux 命令】云服务器 ECS (CentOS) 开启防火墙操作

nuxtjs