好久没发文章了,久到连朋友都开始催我了
这是昨天晚上跟成哥的对话,既然说了今天产出一篇,那今天就一定要产出一篇!
今天就来讲一下前端通往全栈的最后一公里叭,Nest 项目的自动化部署。
初识 Nest.js
先来简单介绍一下 Nest。
Nest 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架。它使用渐进式 JavaScript,内置并完全支持 TypeScript(但仍然允许开发人员使用纯 JavaScript 编写代码)并结合了 OOP(面向对象编程),FP(函数式编程)和FRP(函数式响应编程)的元素。
在底层,Nest 使用强大的 HTTP Server 框架,如 Express(默认) 和 Fastify。Nest 在这些框架之上提供了一定程度的抽象,同时也将其 API 直接暴露给开发人员。这样可以轻松使用每个平台的无数第三方模块。
Nest 也提供了一个开箱即用的应用程序架构,允许开发人员和团队创建高度可测试、可拓展、松散耦合且易于维护的应用程序。
由于本文不是专门写 Nest 开发相关的内容,所以就只介绍这么多,有兴趣的可以自行去 Nest 官网了解更多(nestjs.com/)。
还有一点 Nest !== Next.js。它们两个真的是一点关系都没有,如果真的要说有关系,那可能就是他们都跟 JavaScript有点关系。Next.js 是一个 React 应用程序开发框架,他是基于 React的SSR和SSG的框架,用于构建高性能的 Web 应用程序和静态网站。所以,跟 Nest 真的关系不大,有很多同学会把他们搞混,我这里必须要为 Nest 正名!
emmmm……不好意思,扯远了扯远了。
开始正文
老传统
在讲自动化之前先讲一下传统的部署方案。
- 将本地资源上传到服务器上。
- 安装依赖
- 打包
- 启动服务
自动化部署其实也是这么个流程,只是把整个流程通过流水线作业的形式自动完成,减少开发的任务量以及在部署过程中的出错的概率,毕竟只要指令正确,机器是不会出错的~
自动化
首先,要实现 Nest 项目的自动化部署,那么首先一定要有一个 Nest 项目叭。
我这里已经准备好了,这是我一个练手的项目,把 realworld 的接口都写了一遍。
项目有了之后,在项目的最外层建一个 .github/workflows 的目录,在该目录下创建一个 deploy.yml
编写脚本:
name: Deploy to CentOS Server
on:
push:
branches:
- master
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Copy files to server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
password: ${{ secrets.SERVER_PASSWORD }}
source: './'
target: /home/apps-server/realworld-server/
- name: SSH to server and restart application
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
password: ${{ secrets.SERVER_PASSWORD }}
script: |
cd /home/apps-server/realworld-server
npm install
npm run build
pm2 restart ./dist/src/main.js --name realworld-server
作为一个前端er,我怎么会看得懂这些!这不是运维的兄弟搞得嘛?!
emmmm,看不懂没关系,只要知道语句的意思之后,还是很好理解的。接下来来挨个儿解释一下:
name: 定义步骤的名称,github action 的脚本执行的时候是像流水线一样按步骤一步一步来的,nam 就是给每一个步骤加一个名称,用来标明这个步骤是在做什么事情,也可以理解为流水线上的每个工种的工种名称。 比如这里的 name:
- 对应在git action 里边就是:
on: 定义触发 Github Actions 运行的事件类型,这里触发的是push,分支branch是master,也就是当我们向master分支push代码的时候,会出发当前的流水线作业。jobs: 定义一个或多个需要执行的作业。deploy: deploy 语句通常用于部署代码或应用到目标环境,例如生产环境或测试环境。jobs下边可以有多个deploy。
name: Deploy to Production and Staging
on:
push:
branches:
- master
jobs:
deploy-to-production:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
# Add steps for deployment to production environment
deploy-to-staging:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
# Add steps for deployment to staging environment
例如这段代码,在向maste分支推代码的时候,会执行流水线上的 deploy-to-production 和 deploy-to-staging。哦,对了,需要注意的是,这两个job是并行执行的。
-
runs-on: 用于指定在哪个操作系统中运行job,它允许你在 github actions 中选择一个特定的虚拟机作为 job 的运行环境。它的值可以有这几种形式:- 操作系统名称:例如:
ubuntu-latest、macos-latest、windows-latest,分别表示最新版本的Ubuntu、macOS和Windows操作系统。 - 操作系统版本号:
ubuntu-20.04、macos-11.3、windows-2019,分别表示特定版本的Ubuntu、macOS和Windows操作系统。 - 自定义虚拟机镜像名称,例如:
my-centos-image,表示使用你自己定义的虚拟机镜像。 在每个job中可以使用runs-on指定不同的操作系统,你可以根据需要选择合适的操作系统环境来执行不同的构建、测试、部署等操作。
- 操作系统名称:例如:
-
steps: 定义作业中需要执行的作业。-
name: 也就是任务名称,跟上边的name是一样的 -
uses: 引用外部的 Action,可以是 github上的 Action 或者是 Docker 镜像。- 这里第一步使用了
actions/checkout@v2,它是一个预定义的 github Actions action,用于从指定的仓库中检出代码到当前工作流的工作目录,以便后续步骤可以在该工作目录中执行操作。 - 第二步使用了
appleboy/scp-action@master,它是一个自定义的 github Actions action,用于执行 SCP(Secure Copy Protocol) 命令,用于在不同计算机之间进行文件传输,可以通过配置host、username、port等参数来设置 SSH 连接参数;source是你要复制的资源文件,target是复制之后输出的位置。这里是把上一步检出的内容(也就是master分支)输出到服务器上的/home/apps-server/realworld-server/。 - 第三步使用了
appleboy/ssh-action@master,他是一个 github Actions 自定义的一个 Action,用于在 github Actins 工作流中通过 SSH 远程执行命。它可以用于与远程服务器交互,例如部署应用程序、执行远程命令、上传文件等等;也可以通过配置host、username、port等参数来设置 SSH 连接的参数,并通过script参数来指定要执行的指令。
- 这里第一步使用了
-
with: 用来定义步骤的参数和配置。比如appleboy/scp-action@master和appleboy/ssh-action@master中的主机名和用户名以及用户密码。
-
有些同学可能会问:secrets.SERVER_HOST、secrets.SERVER_USERNAME 这些东西是从哪来的啊?要怎么用呢?
这些其实是在 github 仓库中配置的一些变量,在执行流水线作业的时候会自动读取。
进入到项目的仓库之后,选择 settings tab下的 Actions,然后直接点击 New repository secret 创建就可以了。
SERVER_HOST 就是你的服务器IP地址,如果是云服务器的话就是公网地址。 SERVER_USERNAME 就是登录服务器的用户名。 SERVER_PASSWORD 是登录服务器的用户密码。
可以在仓库的 Actions tab中查看执行了哪些流水线作业,以及任务的状态
点击进去可以查看任务执行的整个流程,以及每一步发生了什么事。
在这里我们可以看到,流水线已经执行完成,并且 pm2 也启动了 realworld-server 的服务。
我们在进入到服务器立板验证一下看看:
现在项目确实已经正常的copy过来了,并且也已经安装了依赖。再来看一下pm2 的 list 里边是否有这项任务:
这里也是正常的。
那要如何检验是否部署成功呢?我在写这些接口的时候也是写了 Swagger 文档的,如果部署成功, Swagger 文档肯定是可以访问的,所以我们来试一下 Swagger 文档能不能访问就好了~
一切正常~
到这里部署的流程其实已经结束了,但是地址是 IP 地址,端口号是 10086……,这实在不怎么好看,而且 ip 也太难记了,所以我想给他解析到我自己的域名上。
打开腾讯云,进入到 DNS 解析 DNSPod 的页面,进入到我的域名下边,然后再操作里边选择解析。
添加一条记录
这样就可以在你的域名上边加一条二级域名
接下来访问一下试试~
非常 Nice~
讲到这里,全文结束~
(哦, 对了,realworld-server 的仓库暂时还是 private 的状态,等我去掉一些敏感信息之后就开源出来~,可能……大概……两三天时间?我比较拖延……)