Git仓库自动部署配置实战:让代码上线不再手忙脚乱

每次改完代码都要手动上传服务器?你不是一个人。上周我朋友小李还在公司加班,就因为一次漏传文件导致网站崩溃。其实,这种重复操作完全可以用 Git 的自动部署搞定。

为什么需要自动部署?

想象一下,你在本地调试好了一个新功能,接着要登录服务器,拉取最新代码,重启服务。这个过程看似简单,但一忙起来就容易出错。特别是团队协作时,多人频繁更新代码,手动同步根本跟不上节奏。

基本原理:监听推送,触发动作

自动部署的核心是“监听”——当你的代码推送到远程仓库(比如 GitHub、GitLab 或 Gitee),服务器收到通知后自动执行更新脚本。整个过程就像快递到了楼下,门禁系统自动给你发短信提醒开门。

以 GitHub + Linux 服务器为例

先在服务器上创建一个 Webhook 接收脚本。这里用一个简单的 Node.js 服务来处理:

const express = require('express');
const { exec } = require('child_process');
const app = express();

app.use(express.json());

app.post('/webhook', (req, res) => {
  if (req.headers['x-github-event'] === 'push') {
    exec('cd /var/www/myproject && git pull origin main && npm run build', (err, stdout, stderr) => {
      console.log(stdout);
      console.error(stderr);
    });
  }
  res.sendStatus(200);
});

app.listen(3000, () => {
  console.log('Webhook 服务运行在 3000 端口');
});

然后在 GitHub 项目的 Settings → Webhooks 里添加地址:http://your-server.com:3000/webhook,事件选择 Just the push event

安全考虑不能少

直接暴露端口有风险,建议加上验证机制。比如在请求头里加个密钥:

if (req.get('X-Auth-Token') !== 'mysecrettoken') {
  return res.status(403).send('Forbidden');
}

同时用 Nginx 反向代理把 3000 端口隐藏起来,外部只暴露 80 或 443。

替代方案:CI/CD 工具更省心

如果你不想自己搭服务,GitHub Actions 是个好选择。在项目根目录加个 .github/workflows/deploy.yml

name: Deploy to Server
on: [push]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Copy files via SSH
        uses: appleboy/scp-action@v0.1.4
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USER }}
          key: ${{ secrets.KEY }}
          source: '.'
          target: '/var/www/myproject'
      - name: Restart service
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USER }}
          key: ${{ secrets.KEY }}
          script: |
            cd /var/www/myproject && npm install && pm2 restart app

只要把服务器的私钥、IP、用户名存进 GitHub Secrets,后续每次 push 都会自动完成部署。

别忘了备份当前状态

自动化虽然方便,但也可能把问题代码一起推上去。建议在执行 git pull 前先打个快照,比如把当前版本打包存到 /backup/ 目录下:

tar -czf /backup/project-$(date +%Y%m%d-%H%M%S).tar.gz /var/www/myproject

万一出事还能快速回滚。

现在小李已经不用加班了。他改完代码一提交,服务器自己就更新好了。你说这不比一遍遍 scp 强?