Vue项目自动部署之二、NuxtJS 发布部署(PM2、GitHub Actions)

传统部署方式

传统部署流程

  • 配置 Host + Port

  • 压缩发布包

  • 把发布包传到服务端

    • Linux 上的 scp 命令
  • 解压

  • 安装依赖

  • 生产环境启动服务

配置 Host + Port

nuxt.config.js中的server属性

  • host
    • 默认 localhost 只能本地访问
    • 对外访问需设置为 0.0.0.0
      • 会监听所有网卡地址
  • port - Nuxt 默认 3000

压缩发布包

需要传到服务器上的文件包括:

  • .nuxt
  • static
  • nuxt.config.js
  • package.json
  • package-lock.json

上传到 Linux 服务器

vscode 终端连接服务器

# 连接服务器
ssh [username]@[ip]
# 展示目录
ls
# 创建目录
mkdir realworld-nuxtjs
# 进入目录
cd realworld-nuxtjs/
# 展示路径
pwd
# 登出
exit
# 上传本地资源到服务器(此时已经退出ssh链接,在本地执行命令)
scp .\realworld-nuxtjs.zip [username]@[ip]:[pwd地址]
# 再次连接服务器
ssh username@ip
# 进入目录
cd realworld-nuxtjs/
# 展示目录
ls
# 解压压缩包(需要服务器已安装unzip)
unzip realworld-nuxtjs.zip
# 查看目录 添加 -a 可以显示隐藏目录 .nuxt
ls -a
# 安装依赖
npm i
# 启动web服务
npm run start

现在就可以使用公网IP+端口号访问(如果访问失败可能是端口未添加对外访问权限)。

使用 PM2 启动 Node 服务

上面在vscode的命令行通过npm run start启动的web服务。

它现在占用着命令行,如果命令行退出,这个服务就关闭了。

pm2 是专门用来管理 Nodejs 进程的应用。

通过它,就可以将 Nodejs 相关的应用,运行在后台,保持运行状态。

当前应用的启动脚本是通过npm启动的,不是执行一个脚本文件,可以 pm2 执行 npm 然后传参:

pm2 start npm -- start
# 此时任务名为npm,自定义名称(--name参数一定要在前面):
# pm2 --name <task_name> start npm -- start

windows 问题

pm2 start npm -- start 在window环境下启动的服务状态是 stopped。

报错日志:

0|RealWorl | :: Created by npm, please don't edit manually.
0|RealWorl | ^
0|RealWorl |
0|RealWorl | SyntaxError: Unexpected token :
0|RealWorl |     at Module._compile (internal/modules/cjs/loader.js:872:18)
0|RealWorl |     at Object.Module._extensions..js (internal/modules/cjs/loader.j
s:947:10)
0|RealWorl |     at Module.load (internal/modules/cjs/loader.js:790:32)
0|RealWorl |     at Function.Module._load (internal/modules/cjs/loader.js:703:12
)
0|RealWorl |     at Object.<anonymous> (D:\software\nvm\v12.10.0\node_modules\pm
2\lib\ProcessContainerFork.js:32:23)
0|RealWorl |     at Module._compile (internal/modules/cjs/loader.js:936:30)
0|RealWorl |     at Object.Module._extensions..js (internal/modules/cjs/loader.j
s:947:10)
0|RealWorl |     at Module.load (internal/modules/cjs/loader.js:790:32)
0|RealWorl |     at Function.Module._load (internal/modules/cjs/loader.js:703:12
)
0|RealWorl |     at Function.Module.runMain (internal/modules/cjs/loader.js:999:
10)

GitHub有人提出了这个问题,里面的变通方案是:https://github.com/Unitech/pm2/issues/2808

也就是使用 node-cmd 运行命令(网上其他的方案也是把npm run start 写在一个脚本文件中,然后用pm2执行):

  1. 安装
npm install node-cmd
  1. 新建脚本 xxx.js
const cmd = require('node-cmd')
cmd.run('npm run start')
  1. pm2 启动脚本
pm2 start xxx.js

执行 pm2 配置文件启动Node服务

项目根目录创建 pm2的配置文件:pm2.config.json

{
  "apps": [
    {
      "name": "RealWorld", // 自定义pm2启动的项目名称
      "script": "npm", // pm2执行的命令
      "args": "start" // 命令参数
    }
  ]
}

执行pm2命令时指定配置文件:

pm2 start pm2.config.json
# 等同于
pm2 start npm -- start

注意:window 环境下同样不生效

PM2 常用命令

命令说明
pm2 list查看应用列表
pm2 start id|name|file启动应用
pm2 stop id|name|all停止应用
pm2 reload id|name|all重载应用(在启动新实例之前,原有实例的进程会一个一个消灭)
pm2 restart id|name|all重启应用(先消灭原有实例的所有进程,然后启动新实例)
pm2 delete id|name|all删除应用(从pm2管理中移除掉)
pm2 kill杀死所有进程
pm2 -h查看所有命令

自动化部署方式

传统部署方式

  • 优点:部署流程比较清晰。
  • 缺点:每次更新都要重复发布流程(本地构建 -> 发布)

现代化的部署方式(CI/CD):

结合 CI/CD 服务工具实现自动部署。

  • CI:持续集成(Continuous integration)
  • CD:持续部署(Continuous deployment)

CI/CD 服务:

  • GitHub Actions
  • Gitee Jenkins
  • GitLab CI
  • Travis CI

在这里插入图片描述

使用GitHub Actions 实现自动化部署

准备工作

  • Linux 服务器 - 发布应用
  • GitHub 仓库 - 托管代码

1. 将项目代码提交到GitHub仓库

2. 在 GitHub 的 Settings 面板创建 token

点击GitHub右上角头像 - Settings - Developer settings - Personal access tokens

生成的个人访问令牌(Token)用于访问GitHub API

在这里插入图片描述

输入密码,创建token,添加对仓库完全访问和操作的权限:

在这里插入图片描述
在这里插入图片描述

生成的token只会出现这一次,如果没有记录,忘记了,只能重新创建一个新的。

3. 在项目根目录创建 GitHub Actions 工作流配置文件

创建目录./github/workflows,在里面创建.yml后缀的文件,文件名随意,将作为工作流的默认名称,GitHub会自动识别到这个文件并执行。

name: Publish And Deploy Demo
on:
  push:
    # 提交tag名以v开头的tag时执行部署任务
    tags:
      - 'v*'

jobs:
  build-and-deploy:
    # 运行环境
    # 启动一个 Docker 的容器,容器中执行的镜像是 ubuntu-latest,所有任务执行完成后,会销毁这个 Docker
    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
      # 生成压缩包(打包 .nuxt static nuxt.config.js package.json package-lock.json pm2.config.json)
      - run: tar -zcvf release.tgz .nuxt static nuxt.config.js package.json package-lock.json pm2.config.json

      # 发布 Release(创建Release分支)
      - name: Create Release
        id: create_release
        uses: actions/create-release@master
        env:
          GITHUB_TOKEN: ${{ secrets.TOKEN }}
        with:
          # 本次提交的tag的名称
          tag_name: ${{ github.ref }}
          # Release版本的名称
          release_name: Release ${{ github.ref }}
          # 是否是草稿
          draft: false
          # 是否是预发布
          prerelease: false

      # 上传构建结果(release.tgz)到 Release
      - name: Upload Release Asset
        id: upload-release-asset
        uses: actions/upload-release-asset@master
        env:
          GITHUB_TOKEN: ${{ secrets.TOKEN }}
        with:
          # 上传地址(创建的Release分支地址)
          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:
          # 远程服务器地址
          host: ${{ secrets.HOST }}
          # 远程服务器用户名
          username: ${{ secrets.USERNAME }}
          # 远程服务器密码
          # 也可以使用密钥,具体查看官方文档 https://github.com/appleboy/ssh-action
          password: ${{ secrets.PASSWORD }}
          # 远程服务器端口号
          port: ${{ secrets.PORT }}
          # 命令超时配置 默认10m
          command_timeout: 20m
          # 运行在远程服务器的命令
          # 1. 进入项目目录
          # 2. 下载发布包
          # 3. 解压缩发布包
          # 4. 安装生产环境依赖
          # 5. pm2运行配置文件
          script: |
            cd /root/realworld-nuxtjs
            wget [Github仓库地址]/releases/latest/download/release.tgz -O release.tgz
            tar zxvf release.tgz
            npm install --production
            pm2 reload pm2.config.json

工作流中使用到了 secrets 信息,即GitHub项目仓库 Settings 中配置的 Secrets。

在这里插入图片描述

需要配置的有(注意名称需要与文件中的保持一致):

  • TOKEN - 之前创建并记录的token
  • HOST - 服务器IP地址
  • USERNAME - 服务器用户名,Linux默认root
  • PASSWORD - 服务器 ssh 连接密码
  • PORT - ssh连接服务器的端口号,默认22

在这里插入图片描述
在这里插入图片描述

4. push代码触发自动部署任务

触发条件:push名称以v开头的 tag。

TortoiseGit方式:

  • 创建标签
  • 推送 - 勾选包括标签

Git 命令方式:

# 创建tag
git tag v0.1.0
# 查看tag
git tag
# 推送tag
push tag origin v0.1.0

然后在GitHub仓库的Actions面板可以查看构建过程。

在这里插入图片描述

构建成功后,使用服务器公网IP+端口号访问。

之后修改内容后,只需重新打 tag 推送到 GitHub 就会自动部署。

遇到的问题

请确认服务器已安装 git、nodejs、pm2 等工具。

本人服务器构建过程中 Deploy 失败,状态码 127。

文件已经解压缩,于是手动连接服务器,执行后面的步骤 npm install --production

最终失败报错:Maximum call stack size exceeded

于是切换npm源为淘宝镜像:npm set registry https://registry.npm.taobao.org/

重新安装,成功。

重新创建tag推送,自动部署又报错:

-bash: npm: command not found
-bash: pm2: command not found

可是手动连接服务器执行都OK(本人是nvm安装的nodejs)。

打印环境变量 echo $PATH 也添加了路径的。

于是在actions任务中执行命令打印 echo $PATH,果然没有 node 路径。

尝试在/root/.bashrc/etc/profile中都添加了 环境变量配置,都没有生效。

又在actions任务中查看文件目录,node、npm、pm2都有。

这个问题的原因是:

手动执行任务时,是在当前 shell 环境下进行的,程序可以找到环境变量。

而系统自动执行任务调度时,是不会加载任何环境变量的,因为它不是通过 shell 环境执行的。

解决办法:

  1. 临时办法:在actions任务中手动添加环境变量:

这个方式就是在每次任务执行时,npm命令执行前手动配置环境变量。

#...
script: |
  export PATH=/root/.nvm/versions/node/v12.17.0/bin:$PATH
  cd /root/realworld-nuxtjs
#...
  1. 长久办法:创建软链接
ln -s [node路径] /usr/local/bin
ln -s [npm路径] /usr/local/bin
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值