博客
关于我
Vue项目自动部署之二、NuxtJS 发布部署(PM2、GitHub Actions)
阅读量:257 次
发布时间:2019-02-28

本文共 7165 字,大约阅读时间需要 23 分钟。

传统部署方式

传统部署流程

  • 配置 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 可以显示隐藏目录 .nuxtls -a# 安装依赖npm i# 启动web服务npm run start

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

使用 PM2 启动 Node 服务

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

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

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

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

  • Github 仓库地址:
  • 官方文档:
  • 全局安装:npm i -g pm2
  • 启动:pm2 start 脚本路径
  • 停止:pm2 stop <app_name|namespace|id|'all'|json_conf>

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

pm2 start npm -- start# 此时任务名为npm,自定义名称(--name参数一定要在前面):# pm2 --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.js: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.
(D:\software\nvm\v12.10.0\node_modules\pm2\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.js: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有人提出了这个问题,里面的变通方案是:

也就是使用 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 Demoon:  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 命令方式:

# 创建taggit tag v0.1.0# 查看taggit tag# 推送tagpush 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/binln -s [npm路径] /usr/local/bin

转载地址:http://efzp.baihongyu.com/

你可能感兴趣的文章
mysql 锁机制 mvcc_Mysql性能优化-事务、锁和MVCC
查看>>
MySQL 错误
查看>>
mysql 随机数 rand使用
查看>>
MySQL 面试题汇总
查看>>
MySQL 面试,必须掌握的 8 大核心点
查看>>
MySQL 高可用性之keepalived+mysql双主
查看>>
mysql 默认事务隔离级别下锁分析
查看>>
Mysql--逻辑架构
查看>>
MySql-2019-4-21-复习
查看>>
mysql-5.7.18安装
查看>>
MySQL-Buffer的应用
查看>>
mysql-cluster 安装篇(1)---简介
查看>>
mysql-connector-java各种版本下载地址
查看>>
mysql-EXPLAIN
查看>>
mysql-group_concat
查看>>
MySQL-redo日志
查看>>
MySQL-【1】配置
查看>>
MySQL-【4】基本操作
查看>>
Mysql-丢失更新
查看>>
Mysql-事务阻塞
查看>>