手把手搭建自定义 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 服务器更好地满足项目的发展需求。

目录
相关文章
|
JSON JavaScript Linux
【MCP教程系列】Node.js+TypeScript搭建NPX MCP服务并自定义部署至阿里云百炼
本文介绍如何将阿里云百炼的工作流封装成MCP服务并部署,随后引入到智能体中使用。主要步骤包括:1) 封装MCP服务;2) 发布到npm官方平台;3) 在阿里云百炼平台创建自定义MCP服务;4) 在智能体中添加自定义MCP服务。通过这些步骤,用户可以轻松将工作流转化为MCP服务,并在智能体中调用。
1918 0
|
8月前
|
人工智能 Kubernetes jenkins
容器化AI模型的持续集成与持续交付(CI/CD):自动化模型更新与部署
在前几篇文章中,我们探讨了容器化AI模型的部署、监控、弹性伸缩及安全防护。为加速模型迭代以适应新数据和业务需求,需实现容器化AI模型的持续集成与持续交付(CI/CD)。CI/CD通过自动化构建、测试和部署流程,提高模型更新速度和质量,降低部署风险,增强团队协作。使用Jenkins和Kubernetes可构建高效CI/CD流水线,自动化模型开发和部署,确保环境一致性并提升整体效率。
|
4月前
|
机器学习/深度学习 Kubernetes 监控
Kubernetes 节点故障自愈方案:结合 Node Problem Detector 与自动化脚本
本文深入探讨了Kubernetes节点故障自愈方案,结合Node Problem Detector(NPD)与自动化脚本,提供技术细节、完整代码示例及实战验证。文章分析了硬件、系统和内核层面的典型故障场景,指出现有监控体系的局限性,并提出基于NPD的实时事件捕获与自动化诊断树的改进方案。通过深度集成NPD、设计自动化修复引擎以及展示内核死锁恢复的实战案例,文章详细说明了自愈流程的实现步骤与性能优势。此外,还提供了生产环境部署指南、高可用架构设计及安全防护措施,并展望了机器学习增强故障预测和混沌工程验证的进阶优化方向。全文约1.2万字,适合希望提升Kubernetes集群稳定性的技术人员阅读。
147 1
|
8月前
|
弹性计算 JavaScript 前端开发
一键安装!阿里云新功能部署Nodejs环境到ECS竟然如此简单!
Node.js 是一种高效的 JavaScript 运行环境,基于 Chrome V8 引擎,支持在服务器端运行 JavaScript 代码。本文介绍如何在阿里云上一键部署 Node.js 环境,无需繁琐配置,轻松上手。前提条件包括 ECS 实例运行中且操作系统为 CentOS、Ubuntu 等。功能特点为一键安装和稳定性好,支持常用 LTS 版本。安装步骤简单:登录阿里云控制台,选择扩展程序管理页面,安装 Node.js 扩展,选择实例和版本,等待创建完成并验证安装成功。通过阿里云的公共扩展,初学者和经验丰富的开发者都能快速进入开发状态,开启高效开发之旅。
|
8月前
|
弹性计算 JavaScript 前端开发
一键安装!阿里云新功能部署Nodejs环境到ECS竟然如此简单!
一键安装!阿里云新功能部署Nodejs环境到ECS竟然如此简单!
一键安装!阿里云新功能部署Nodejs环境到ECS竟然如此简单!
|
9月前
|
Kubernetes Java 持续交付
小团队 CI/CD 实践:无需运维,Java Web应用的自动化部署
本文介绍如何使用GitHub Actions和阿里云Kubernetes(ACK)实现Java Web应用的自动化部署。通过CI/CD流程,开发人员无需手动处理复杂的运维任务,从而提高效率并减少错误。文中详细讲解了Docker与Kubernetes的概念,并演示了从创建Kubernetes集群、配置容器镜像服务到设置GitHub仓库Secrets及编写GitHub Actions工作流的具体步骤。最终实现了代码提交后自动构建、推送镜像并部署到Kubernetes集群的功能。整个过程不仅简化了部署流程,还确保了应用在不同环境中的稳定运行。
446 9
Node:http-server开启静态服务器
Node:http-server开启静态服务器
265 0
|
3月前
|
JavaScript Unix Linux
nvm与node.js的安装指南
通过以上步骤,你可以在各种操作系统上成功安装NVM和Node.js,从而在不同的项目中灵活切换Node.js版本。这种灵活性对于管理不同项目的环境依赖而言是非常重要的。
801 11
|
7月前
|
资源调度 JavaScript 前端开发
前端开发必备!Node.js 18.x LTS保姆级安装教程(附国内镜像源配置)
本文详细介绍了Node.js的安装与配置流程,涵盖环境准备、版本选择(推荐LTS版v18.x)、安装步骤(路径设置、组件选择)、环境验证(命令测试、镜像加速)及常见问题解决方法。同时推荐开发工具链,如VS Code、Yarn等,并提供常用全局包安装指南,帮助开发者快速搭建高效稳定的JavaScript开发环境。内容基于官方正版软件,确保合规性与安全性。
5893 24
|
8月前
|
JavaScript 前端开发 数据可视化
【01】Cocos游戏开发引擎从0开发一款游戏-cocos环境搭建以及配置-Cocos Creator软件系统下载安装-node环境-优雅草卓伊凡
【01】Cocos游戏开发引擎从0开发一款游戏-cocos环境搭建以及配置-Cocos Creator软件系统下载安装-node环境-优雅草卓伊凡
434 2
【01】Cocos游戏开发引擎从0开发一款游戏-cocos环境搭建以及配置-Cocos Creator软件系统下载安装-node环境-优雅草卓伊凡

热门文章

最新文章