nodejs 如何实现自动化部署?

3,250 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

什么是自动化部署

我接触到的自动化部署概念最早是在 Vercel 上提供的,Vercel 可以提供和 github 联动的功能,通过和你自己的 github 上的某个库建立‘链接’,当你 commitgithub 远程库时就可以自动部署,Vercel 会帮你完成以下操作(例子为一个 Webpack 项目,仅限 Web 前端,如有遗漏望补充)

  1. Webpack 打包(默认是项目 package.json 的打包命令)
  2. 打包文件迁移到 Vercel 的服务器上(dist 目录下的文件)
  3. 部署网站(Vercel 使用的 Nginx 还是 Apache 我就不知道了,应该是用的 Nginx

另一个自动化部署概念是在实习时接触的,公司称之为流水线,它的作用和 Vercel 差不多,不过会多了两个步骤

  1. ESLint 校验代码
  2. 重新安装依赖
  3. Webpack 打包(默认是项目 package.json 的打包命令)
  4. 打包文件迁移到 Vercel 的服务器上(dist 目录下的文件)
  5. 部署网站(Vercel 使用的 Nginx 还是 Apache 我就不知道了,应该是用的 Nginx

现在自动化部署的概念炒的火热,主要是它通常还可以和 Serverless 绑定在一起,Serverless 意思是无服务器,其实就是托管应用程序到 Serverless 服务提供商的服务器上,像一些小微公司可以直接托管网站、小程序,完全不用买服务器(为啥不买服务器,因为 Serverless 便宜呀)

Serverless、自动化部署和它们的可视化界面就不多介绍了,但我要说腾讯云在这方面做的很烂,相反 AzureVercel 做的就很好

普通部署

说完了自动化部署那么我们平常的普通部署是怎么做的呢?以一个 nodejs 的普通接口为例(基于 express-generator 生成的项目)

# npm v5.2.0 以上版本
npx express --no-view --git
git init
npm install

执行上面的命令后得到下面的目录结构

├── .git/
├── bin/
├── node_modules/
├── public/
├── routes/
├── .gitignore
├── app.js
├── package-lock.json
└── package.json
  1. 第一步,在宝塔安装 pm2 如果你没有的话(pm2 会自动安装 nodejsnpm

IMG

  1. 第二步,在服务器找到一个地方放你的文件,这里项目比较小,我就直接丢上去了(一般使用 zip 压缩文件,或者在服务器上重新执行 npm install

IMG

  1. 第三步,在你的 PM2 面板里面添加项目

IMG

IMG

  1. 第四步,提交查看效果,是否符合本地运行预期

IMG

后续重新更新部署怎么办?很简单,将更新的文件覆盖掉原文件,在 PM2 重启一下就行了

IMG

但是如果我想本地 git 提交代码到远程库的时候能够顺便部署行不行呢?看下面的操作

自动化部署

本篇文章实现的自动化部署是基于 githubWebhooks 和宝塔的 WebHook 实现

那如何将上面的普通部署改成这个自动化部署呢?

  1. 第一步,在 github 上创建对应的库(反正又不要钱,随便创)

库链接 - pandoralink/auto-deploy

IMG

  1. 第二步,在服务器拉取项目并在在 PM2 添加项目(同普通部署) 并查看 id 信息
cd /www/temp
git clone git@github.com:pandoralink/auto-deploy.git
cd auto-deploy
npm install
# 查看 Linux 的 PM2 项目 id 信息
pm2 list

id 信息如下图

IMG

Linux 操作 git 添加公钥私钥到远程仓库(github/gitee)可以参考 服务器上的 Git - 生成 SSH 公钥远程仓库 - 远程仓库

  1. 第三步,安装宝塔 WebHook 插件

IMG

  1. 第四步,添加宝塔 WebHook 规则

IMG

  1. 第五步,获取宝塔 WebHook URL

IMG

  1. 第六步,配置 githubWebHooks

IMG

注意content-type 需要选择 application/json,否则 github 请求此 URL 时,宝塔会返回 403 错误

配置结果如图

IMG

测试修改一下 public/index.html 的内容,并 pushgithub 远程仓库

IMG

成功修改并部署成功,结果如下

IMG

填坑

2023/09/25 更新

自动化部署算是我反馈比较多的一篇文章,其实这不是没有原因的,因为在自动化部署这块出现了问题,原有的自动部署在静态文件是没有问题的,因为对于 pm2 启动的进程来说,都是拿的相对路径并返回,比如

git pull                     // 更新 public | dist 这些静态文件
请求服务
nodejs 服务返回对应路径的文件 // 只要路径对应的文件更新就会自动更新

但是对于接口一类文件,比如 route/controller,这些不是文件更新了就行,还需要 pm2 restart 才可以,因为 pm2 执行的时候会用缓存(其实就是把硬盘的内容放到内存),所以需要 pm2 restart,重点来了

pm2 restart 未执行成功原因

这可能和宝塔的 webhook 的执行用户有关

在测试中,虽然我用 whoami 打印出来是 root,但实际表现和我用 root 用户登录执行的结果不一致

最终解决方案,是使用使用 su - root -c "pm2 restart ${pid}",解决了这个问题

令人疑惑的解决方案,自己已经是 root 却还要使用 su - root -c 这个命令指定 root 角色执行指定命令,有好奇心的同学可以拿这篇文章去问问宝塔官方~

最终的宝塔脚本为

echo $(date "+%Y-%m-%d %H:%M:%S") 开始部署
cd /www/wwwroot/nodejs/auto-deploy
git pull
su - root -c "pm2 restart ${pid}" # ${pid} pm2 项目 id, e.g. pm2 restart 5
echo $(date "+%Y-%m-%d %H:%M:%S") 重启成功

PS: 不要使用 pm2 项目的名称,不能成功启动

快去试试这个前后端都能够重新部署的全新版本吧!

总结

相比于 Vercel 还是我实习公司的流水线,文章中实现的自动化部署还是过于简陋,成熟的自动化部署拥有可视化界面,完善的日志,部署进度条,这些都是需要很多努力和经验去实现的,最后给出自动化部署的流程图

IMG

参考资料

  1. 如何使用 Github webhook 配合宝塔 webhook 自动化部署 - 無糖