手把手搭建自定义 CI/CD 服务器,实现 Node.js 部署自动化

简介: 本文介绍如何搭建一个基于 GitHub Webhooks、PM2 和 Shell 脚本的轻量级 Node.js 自定义 CI/CD 服务器,实现自动化部署。通过实时监听代码变动、验证请求合法性、自动执行部署及反馈状态等功能,提升开发效率,确保项目稳定运行。内容涵盖环境准备、代码实现、服务器配置及功能测试,适合需要自动化部署的 Node.js 项目。

在 Node.js 项目开发进程中,随着项目规模的不断扩大,手动部署所带来的弊端愈发凸显。


频繁的代码更新需要人工操作来完成部署,不仅耗费大量时间,还容易因人为失误导致环境不一致、依赖缺失等问题,严重影响开发效率与项目稳定性。


而一套设计合理的持续集成 / 持续部署(CI/CD)流水线,能有效解决这些痛点。本文将详细介绍如何利用 GitHub Webhooks、PM2 和 Shell 脚本,搭建一个自定义的 CI/CD 服务器,实现 Node.js 应用的自动化部署。


一、了解自定义 CI/CD 服务器核心功能


本次搭建的轻量级 Node.js CI/CD 服务器,具备以下关键能力,为 Node.js 项目部署保驾护航:


  1. 实时监听代码变动:能够时刻监听 GitHub 仓库特定分支的代码提交事件,一旦有新的代码推送,立即触发后续部署流程,确保项目能及时获取最新代码。
  2. 请求合法性验证:在接收到 GitHub Webhook 发送的请求时,会对请求 payload 进行验证,只有确认请求来自 GitHub,才会执行部署操作,保障服务器安全,防止恶意请求干扰部署流程。
  3. 自动化部署执行:通过执行 Shell 脚本(deploy.sh),完成一系列部署操作,包括切换到对应项目目录、拉取最新代码、检查并安装缺失的依赖、使用 PM2 重启项目,确保项目以最新状态稳定运行。
  4. 部署状态反馈:在部署过程中,会将部署的相关状态信息发送给 GitHub 进行日志记录,方便开发人员随时查看部署情况,及时发现并解决部署中出现的问题。


二、搭建前的准备工作


在正式搭建 CI/CD 服务器之前,需要确保服务器满足以下 prerequisites,为后续搭建工作奠定基础:


  1. Node.js 环境:需安装 16 版本及以上的 Node.js。可通过 vim 工具下载,也能直接从包管理器中安装,Node.js 是运行 CI/CD 服务器代码的基础环境。
  2. PM2 进程管理工具:用于高效管理 Node.js 应用,能实现应用的启动、停止、重启等操作,保证应用稳定运行。可通过npm install -g pm2命令进行全局安装。
  3. Git 版本控制工具:用于从 GitHub 仓库拉取最新代码,是获取项目更新的关键工具。在 AlmaLinux 系统中,可通过sudo dnf install git -y命令安装。
  4. Web 服务器(可选):若需要通过域名暴露 CI/CD 服务器,可选择安装 NGINX 或 Apache 作为反向代理,实现域名与服务器的映射。
  5. GitHub 仓库设置:确保待部署的项目已托管在 GitHub 上,并且拥有配置 Webhooks 的权限,以便实现代码提交与部署流程的联动。

三、逐步搭建 CI/CD 服务器

(一)初始化 Node.js 项目


首先,为 CI/CD 服务器创建一个专门的目录,并在该目录下初始化 Node.js 项目,具体操作如下:


  1. 打开服务器终端,执行mkdir ~/cicd-server && cd ~/cicd-server命令,创建并进入 CI/CD 服务器目录。
  2. 执行npm init -y命令,快速初始化 Node.js 项目,生成 package.json 文件,该文件将记录项目的依赖信息等配置。
  3. 安装项目所需的依赖包,执行npm install express body-parser crypto命令。其中,express 用于搭建 Web 服务器,body-parser 用于解析请求体,crypto 用于进行数据加密,验证 GitHub Webhook 请求的合法性。


(二)构建 Webhook 监听器


Webhook 监听器是 CI/CD 服务器的核心部分,负责接收 GitHub Webhook 发送的请求并进行处理。创建一个名为 index.js 的文件,写入以下代码:


const express = require("express");
const bodyParser = require("body-parser");
const crypto = require("crypto");
const { exec } = require("child_process");
const app = express();
const PORT = 4000;
// 从环境变量获取GitHub密钥,若未设置则使用默认密钥,实际生产环境建议从环境变量获取,提高安全性
const GITHUB_SECRET = process.env.GITHUB_SECRET || "your-secret-key";
// 解析JSON格式的请求体
app.use(bodyParser.json());
// 处理GitHub Webhook发送的POST请求
app.post("/webhook", (req, res) => {
    // 生成请求签名,用于验证请求是否来自GitHub
    const signature = `sha256=${crypto
        .createHmac("sha256", GITHUB_SECRET)
        .update(JSON.stringify(req.body))
        .digest("hex")}`;
    // 对比请求头中的签名与生成的签名,验证请求合法性
    if (req.headers["x-hub-signature-256"] !== signature) {
        return res.status(401).json({ message: "Invalid signature" });
    }
    // 获取仓库名称
    const repoName = req.body.repository.name;
    console.log(`Received update for: ${repoName}`);
    // 执行部署脚本,传入仓库名称作为参数
    exec(`bash ./deploy.sh ${repoName}`, (error, stdout, stderr) => {
        if (error) {
            console.error(`Deployment failed: ${stderr}`);
            return res.status(500).json({ message: "Deployment failed", error: stderr });
        }
        console.log(`Deployment successful: ${stdout}`);
        res.json({ message: "Deployment successful", output: stdout });
    });
});
// 启动服务器,监听指定端口
app.listen(PORT, () => console.log(`CI/CD server running on port ${PORT}`));


(三)编写部署脚本


部署脚本(deploy.sh)用于执行具体的部署操作,包括拉取代码、安装依赖、重启项目等。在 CI/CD 服务器目录下创建 deploy.sh 文件,写入以下代码:

#!/bin/bash
# 获取传入的仓库名称参数
REPO_NAME=$1
# 项目基础目录,可根据实际情况修改
BASE_DIR="/var/www/projects"
# 具体项目目录
PROJECT_DIR="$BASE_DIR/$REPO_NAME"
echo "Starting deployment for $REPO_NAME..."
# 检查项目目录是否存在,若不存在则输出错误信息并退出
if [ ! -d "$PROJECT_DIR" ]; then
    echo "Error: Directory $PROJECT_DIR does not exist."
    exit 1
fi
# 切换到项目目录
cd "$PROJECT_DIR"
echo "Pulling latest changes..."
# 从GitHub仓库主分支拉取最新代码,若项目使用其他分支,需将main改为对应分支名称
git pull origin main
# 获取上一次提交与本次提交之间的文件变更列表
CHANGES=$(git diff --name-only HEAD@{1} HEAD)
# 检查变更文件中是否包含package.json,若包含则说明依赖可能发生变化,执行npm install安装依赖
if [[ $CHANGES == *"package.json"* ]]; then
    echo "Detected dependency changes. Running npm install..."
    npm install
fi
# 使用PM2重启项目,确保项目以最新代码运行
echo "Restarting application..."
pm2 restart $REPO_NAME
echo "Deployment completed."


编写完成后,执行chmod +x deploy.sh命令,为脚本添加可执行权限,使其能够正常运行。


(四)配置 GitHub Webhooks


要实现 GitHub 仓库代码提交与 CI/CD 服务器部署的联动,需要在 GitHub 仓库中配置 Webhooks,具体步骤如下:


  1. 登录 GitHub 账号,进入对应的项目仓库,点击仓库页面右上角的 “Settings” 选项,进入仓库设置页面。


  1. 在设置页面左侧的导航栏中,找到并点击 “Webhooks” 选项,进入 Webhooks 配置页面。


  1. 点击页面右上角的 “Add webhook” 按钮,进入添加 Webhook 页面。


  1. 在 “Payload URL” 输入框中,填写 CI/CD 服务器的 Webhook 接收地址,格式为http://server-ip:4000/webhook。若已配置 NGINX 或 Apache 反向代理,可将 server-ip 替换为对应的域名,如http://example.com/webhook


  1. 在 “Content type” 下拉菜单中,选择 “application/json”,指定请求体的格式为 JSON。


  1. 在 “Secret” 输入框中,填写与 CI/CD 服务器 index.js 文件中 GITHUB_SECRET 相同的值,用于验证请求的合法性。


  1. 在 “Which events would you like to trigger this webhook?” 部分,选择 “Let me select individual events.”,然后勾选 “Just the push event.”,确保只有在代码推送时才触发 Webhook。


  1. 确认所有配置信息无误后,点击页面底部的 “Add webhook” 按钮,完成 GitHub Webhooks 的配置。


(五)启动 CI/CD 服务器


配置完成后,启动 CI/CD 服务器,使其能够监听 GitHub Webhook 发送的请求,具体操作如下:


  1. 在 CI/CD 服务器目录下,执行pm2 start index.js --name cicd-server命令,使用 PM2 启动 CI/CD 服务器,并为其指定名称 “cicd-server”,方便后续管理。


  1. 执行pm2 save命令,将当前 PM2 管理的进程列表保存到配置文件中,确保服务器重启后,CI/CD 服务器能够自动启动。


(六)配置反向代理(可选)


若需要通过域名访问 CI/CD 服务器,可配置 NGINX 或 Apache 作为反向代理,以下分别介绍两种服务器的配置方法:


1. NGINX 配置

  1. 执行sudo nano /etc/nginx/conf.d/cicd.conf命令,创建并编辑 NGINX 配置文件。


  1. 在配置文件中写入以下内容:

server {
    listen 80;
    # 替换为实际使用的域名
    server_name example.com;
    location / {
        # 代理到CI/CD服务器的地址和端口
        proxy_pass http://localhost:4000;
        # 设置请求头信息,确保客户端信息能正确传递到CI/CD服务器
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}


  1. 保存并退出配置文件,执行sudo nginx -t命令,检查 NGINX 配置是否正确。若配置正确,会输出 “test is successful” 的提示信息。


  1. 执行sudo systemctl reload nginx命令,重新加载 NGINX 配置,使配置生效。


2. Apache 配置

  1. 执行sudo nano /etc/httpd/conf.d/cicd.conf命令,创建并编辑 Apache 配置文件。


  1. 在配置文件中写入以下内容:


<VirtualHost *:80>
    # 替换为实际使用的域名
    ServerName example.com
    # 将请求代理到CI/CD服务器
    ProxyPass / http://localhost:4000/
    ProxyPassReverse / http://localhost:4000/
    # 配置错误日志和访问日志的路径
    ErrorLog /var/log/httpd/cicd-error.log
    CustomLog /var/log/httpd/cicd-access.log combined
</VirtualHost>


  1. 保存并退出配置文件,执行sudo systemctl restart httpd命令,重启 Apache 服务,使配置生效。


四、测试 CI/CD 服务器功能


完成 CI/CD 服务器的搭建和配置后,需要对其功能进行测试,确保能够正常实现自动化部署,具体测试步骤如下:


  1. 对本地 Node.js 项目进行修改,例如修改代码中的某个功能或添加一些注释。
  2. 将修改后的代码提交到 GitHub 仓库的对应分支(与 Webhooks 配置中选择的分支一致),执行git add .git commit -m "测试CI/CD部署"git push origin main(若分支不是 main,需替换为实际分支名称)命令。
  3. 登录 CI/CD 服务器,执行pm2 logs cicd-server命令,查看 CI/CD 服务器的日志信息,观察是否接收到 GitHub Webhook 发送的请求,以及部署脚本是否正常执行。
  4. 检查项目目录下的代码是否已更新为最新版本,若 package.json 文件有变更,查看依赖是否已重新安装。
  5. 执行pm2 status命令,查看项目是否已被 PM2 成功重启,确保项目以最新代码正常运行。


五、总结


通过以上步骤,我们成功搭建了一个自托管的 CI/CD 流水线,实现了 Node.js 应用的自动化部署。


该方案具有 lightweight、cost-effective 的特点,能够有效减少手动部署的工作量,提高开发效率,保障项目部署的稳定性和一致性。


同时,它还支持多项目管理,可通过在 CI/CD 服务器上配置多个项目的部署脚本和 GitHub Webhooks,实现对多个 Node.js 项目的自动化部署管理。


在实际使用过程中,可根据项目的具体需求,对部署脚本和服务器配置进行进一步的优化和扩展,例如添加部署失败的邮件通知功能、实现多环境部署等,使 CI/CD 服务器更好地满足项目的发展需求。

目录
相关文章
|
7天前
|
人工智能 运维 安全
|
5天前
|
人工智能 异构计算
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
|
6天前
|
机器学习/深度学习 人工智能 自然语言处理
B站开源IndexTTS2,用极致表现力颠覆听觉体验
在语音合成技术不断演进的背景下,早期版本的IndexTTS虽然在多场景应用中展现出良好的表现,但在情感表达的细腻度与时长控制的精准性方面仍存在提升空间。为了解决这些问题,并进一步推动零样本语音合成在实际场景中的落地能力,B站语音团队对模型架构与训练策略进行了深度优化,推出了全新一代语音合成模型——IndexTTS2 。
591 21
|
12天前
|
人工智能 JavaScript 测试技术
Qwen3-Coder入门教程|10分钟搞定安装配置
Qwen3-Coder 挑战赛简介:无论你是编程小白还是办公达人,都能通过本教程快速上手 Qwen-Code CLI,利用 AI 轻松实现代码编写、文档处理等任务。内容涵盖 API 配置、CLI 安装及多种实用案例,助你提升效率,体验智能编码的乐趣。
958 110
|
6天前
|
人工智能 测试技术 API
智能体(AI Agent)搭建全攻略:从概念到实践的终极指南
在人工智能浪潮中,智能体(AI Agent)正成为变革性技术。它们具备自主决策、环境感知、任务执行等能力,广泛应用于日常任务与商业流程。本文详解智能体概念、架构及七步搭建指南,助你打造专属智能体,迎接智能自动化新时代。

热门文章

最新文章