轻量级 CI/CD:Git Hooks 自动部署 Node.js 应用(CICD-demo)

从零实现一个轻量级 CI/CD:Git Hooks 自动部署 Node.js 应用(含 Nginx + systemd 生产级配置)

作者:粟本偲

项目地址:https://gitcode.com/SUBENCAI/myapp-cicd-demo

适用场景:CentOS 7 / Node.js / 运维开发学习 /

本文记录了我如何仅用 Shell 脚本 + Git Hooks 实现一套轻量级 CI/CD 系统,并完成 Node.js 应用的 生产级部署(Nginx 反向代理 + systemd 托管)。全程无需 Jenkins/GitLab CI,适合学习原理与面试展示。

一、为什么不用 Jenkins?------ 我们要理解 CI/CD 的本质

  • CI/CD 的核心是:代码变更 → 自动构建 → 自动部署
  • 大多数人只会点图形界面,但不知道背后是 Shell 脚本在执行
  • 本文通过 post-receive 钩子,亲手实现这一流程

二、环境准备

  • 操作系统:CentOS 7(阿里云 ECS)

  • 已安装软件:Git、Nginx、Node.js(通过 EPEL + 阿里源)

  • 用户权限:root 或 sudo 权限

    node -v # ≥ v14
    nginx -v
    git --version

三、创建裸仓库(Bare Repository)

  • 在服务器创建 /var/git/myapp.git

  • 初始化为 bare 仓库:git init --bare

  • 设置目录权限,确保部署用户可写

    在服务器上创建接收推送的裸仓库:
    mkdir -p /var/repo/myapp.git
    cd /var/repo/myapp.git
    git init --bare

    [root@python myapp]# mkdir -p /var/repo/myapp.git
    [root@python myapp]# cd /var/repo/myapp.git
    [root@python myapp.git]# git init --bare
    初始化空的 Git 版本库于 /var/repo/myapp.git/

四、编写 post-receive 钩子脚本

  • 路径:/var/git/myapp.git/hooks/post-receive

  • 功能:

    • 拉取最新代码到 /var/www/myapp/releases/v{timestamp}
    • 创建软链接 /var/www/myapp/current 指向最新版本
    • 自动清理超过 3 个历史版本
    • 重启 systemd 服务
  • 关键技巧:使用 flock 避免并发冲突

    #!/bin/bash
    GIT_WORK_TREE=/root/myapp git --git-dir=/var/repo/myapp.git checkout -f
    systemctl restart myapp
    echo "$(date): Deployed" >> /var/log/myapp-deploy.log

五、Node.js 应用示例(app.js)

  • 简单 HTTP 服务,返回 "Hello from CI/CD!"

  • 包含 package.json(定义 start 脚本)

  • 日志输出到 stdout(便于 systemd 收集)

    const http = require('http');
    const server = http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Hello from CI/CD!\n');
    });
    server.listen(3000, '0.0.0.0', () => {
    console.log('Server running at http://0.0.0.0:3000/');
    });

六、配置 systemd 托管服务

  • 创建 /etc/systemd/system/myapp.service

  • 设置 User、WorkingDirectory、ExecStart

  • 启用开机自启:systemctl enable myapp

  • 查看日志:journalctl -u myapp -f

    /etc/systemd/system/myapp.service
    [Unit]
    Description=MyApp Node.js Service
    After=network.target

    [Service]
    ExecStart=/usr/bin/node /root/myapp/app.js
    WorkingDirectory=/root/myapp
    Restart=always
    User=root
    Environment=NODE_ENV=production

    [Install]
    WantedBy=multi-user.target

    启用服务:
    systemctl daemon-reload
    systemctl start myapp
    systemctl enable myapp

七、Nginx 反向代理配置

  • 配置文件:/etc/nginx/conf.d/myapp.conf

  • 将 80 端口请求代理到 http://127.0.0.1:3000

  • 添加健康检查路径 /healthz

  • 重载 Nginx:nginx -s reload

    /etc/nginx/conf.d/myapp.conf

    server {
    listen 80;
    server_name _;

    复制代码
      location / {
          proxy_pass http://127.0.0.1:3000;
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
      }

    }

八、本地开发与推送测试

  • 本地添加远程仓库:git remote add prod root@server:/var/git/myapp.git

  • 推送触发部署:git push prod main

  • 验证:curl http://192.168.126.50

    初始化本地仓库

    git init
    git add .
    git commit -m "First deploy"

    添加远程仓库

    git remote add prod root@192.168.126.50:/var/repo/myapp.git

    推送触发自动部署

    git push prod master

九、效果展示与性能对比

  • 部署耗时:<5 秒
  • 回滚操作:手动切换软链接即可
  • 对比 Jenkins:资源占用更低,逻辑透明可控

十、总结与延伸思考

优势

轻量:仅依赖系统自带工具

可控:无隐藏逻辑,适合调试

教学友好:清晰展示 CI/CD 本质

不足

无 Web UI

无并行流水线

无权限管理

下一步优化方向

增加版本回滚(软链接切换)

集成健康检查(/healthz)

添加邮件/企业微信告警

使用非 root 用户部署(安全加固)

💡 项目已开源,欢迎 Star:https://gitcode.com/SUBENCAI/myapp-cicd-demo

技术栈:Shell / Git / Node.js / Nginx / systemd / CentOS

相关推荐
XiaoHamao4 小时前
Git 核心分区全解析
git
XiaoHamao5 小时前
git stash:优雅处理未完成的代码改动
git
旧梦星轨5 小时前
掌握 Vite 环境配置:从 .env 文件到运行模式的完整实践
前端·前端框架·node.js·vue·react
曲莫终5 小时前
Git删除过去分支(如删除23年及之前的分支)
git
一过菜只因5 小时前
Git入门学习
git·学习
weixin_307779135 小时前
Jenkins声明式流水线权威指南:从Model API基础到高级实践
开发语言·ci/cd·自动化·jenkins·etl
嘻哈baby6 小时前
Jenkins自动化构建与CI/CD流水线实战
ci/cd·自动化·jenkins
小鸡脚来咯7 小时前
java web后端开发流程
java·开发语言·git
qq_348231857 小时前
面向初学者到进阶者的 Node.js 学习指南
node.js
大猫和小黄7 小时前
Windows 下使用 NVM 管理多个 Node.js 版本
windows·node.js