每次改完代码都要手动上传服务器?你不是一个人。上周我朋友小李还在公司加班,就因为一次漏传文件导致网站崩溃。其实,这种重复操作完全可以用 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 强?