从手动部署到全自动CI/CD,我只用了30分钟
前言
还记得刚做开发那会儿,每次改完代码都要手动打包、上传服务器、重启服务,一套流程下来至少10分钟。要是遇到紧急bug修复,这种”人肉部署”简直让人崩溃。
直到我发现了 GitHub Actions —— GitHub官方提供的CI/CD工具,免费、易用、生态丰富。今天就把我踩过的坑和最佳实践分享给你。
一、GitHub Actions是什么?
1.1 核心概念
GitHub Actions 是 GitHub 提供的持续集成/持续部署(CI/CD)平台,让你可以在代码仓库中直接定义自动化工作流。
代码推送 → 触发Workflow → 自动构建 → 自动测试 → 自动部署
1.2 为什么选它?
| 特性 | GitHub Actions | Jenkins | GitLab CI |
|---|---|---|---|
| 学习成本 | ⭐⭐ 低 | ⭐⭐⭐⭐ 高 | ⭐⭐⭐ 中 |
| 配置方式 | YAML文件 | 插件配置 | YAML文件 |
| 免费额度 | 2000分钟/月 | 自建服务器 | 400分钟/月 |
| 生态丰富度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| 与GitHub集成 | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐ |
结论:如果你的代码已经在GitHub上,GitHub Actions是最省心的选择。
二、快速上手:5分钟搭建第一个工作流
2.1 创建Workflow文件
在你的项目根目录创建:
.github/workflows/deploy.yml
2.2 前端项目部署示例(Vue/React)
name: Deploy Frontend
# 触发条件:main分支有push时触发
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
# 1. 检出代码
- name: Checkout code
uses: actions/checkout@v4
# 2. 设置Node.js环境
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
# 3. 安装依赖
- name: Install dependencies
run: npm ci
# 4. 构建项目
- name: Build project
run: npm run build
# 5. 部署到服务器(通过SSH)
- name: Deploy to server
uses: appleboy/[email protected]
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
source: "dist/"
target: "/var/www/html/"
strip_components: 1
2.3 配置Secrets(密钥)
在GitHub仓库 → Settings → Secrets and variables → Actions 中添加:
| Secret名称 | 说明 |
|---|---|
HOST |
服务器IP地址 |
USERNAME |
SSH用户名 |
PASSWORD |
SSH密码(或密钥) |
安全提示:永远不要将密码直接写在YAML文件中!
三、后端项目部署实战(Node.js/Python)
3.1 Node.js + PM2 部署方案
name: Deploy Backend API
on:
push:
branches: [ main ]
paths:
- 'server/**' # 只有server目录变化时才触发
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: |
cd server
npm ci --production
# 使用SSH命令部署并重启服务
- name: Deploy and restart
uses: appleboy/[email protected]
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /opt/myapp
git pull origin main
cd server
npm ci --production
pm2 restart app.js --name "api-server"
pm2 save
3.2 Python + Docker 部署方案
name: Deploy Python API with Docker
on:
push:
branches: [ main ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
# 登录GitHub Container Registry
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# 构建并推送Docker镜像
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
# 在服务器上拉取并运行新镜像
- name: Deploy to server
uses: appleboy/[email protected]
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
docker stop api-container || true
docker rm api-container || true
docker run -d \
--name api-container \
-p 8000:8000 \
--restart unless-stopped \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
四、进阶技巧:让部署更智能
4.1 条件部署(只在特定情况下触发)
on:
push:
branches: [ main ]
paths:
- 'src/**' # 源码变化时
- 'package.json' # 依赖变化时
paths-ignore:
- '**.md' # 忽略文档修改
- 'docs/**'
4.2 多环境部署(开发/测试/生产)
name: Multi-Environment Deploy
on:
push:
branches:
- develop # 开发环境
- main # 生产环境
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to Development
if: github.ref == 'refs/heads/develop'
run: |
echo "Deploying to DEV environment..."
# 部署到测试服务器
- name: Deploy to Production
if: github.ref == 'refs/heads/main'
run: |
echo "Deploying to PROD environment..."
# 部署到生产服务器
4.3 添加自动化测试
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test
- name: Build check
run: npm run build
deploy:
needs: test # 测试通过后才部署
runs-on: ubuntu-latest
steps:
# ... 部署步骤
4.4 缓存加速(节省时间和额度)
steps:
- uses: actions/checkout@v4
# 缓存node_modules
- name: Cache dependencies
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm ci
五、常见问题与解决方案
5.1 部署失败排查清单
# 1. 检查Workflow语法
gitHub仓库 → Actions → 查看具体错误
# 2. 检查Secrets是否正确设置
Settings → Secrets and variables → Actions
# 3. 检查SSH连接
# 在本地测试:
ssh -i ~/.ssh/id_rsa user@host
# 4. 检查服务器权限
# 确保部署目录有写入权限
sudo chown -R $USER:$USER /var/www/html
5.2 常见错误及解决
| 错误信息 | 原因 | 解决方案 |
|---|---|---|
Permission denied (publickey) |
SSH密钥错误 | 检查Secrets中的SSH_KEY格式 |
No such file or directory |
路径错误 | 确认服务器上的目标路径存在 |
EACCES: permission denied |
权限不足 | 使用sudo或修改目录权限 |
Process completed with exit code 1 |
构建失败 | 检查构建命令和依赖 |
六、完整项目结构示例
my-project/
├── .github/
│ └── workflows/
│ ├── deploy-frontend.yml # 前端部署
│ ├── deploy-backend.yml # 后端部署
│ └── test.yml # 自动化测试
├── frontend/ # 前端代码
│ ├── src/
│ └── package.json
├── backend/ # 后端代码
│ ├── src/
│ └── requirements.txt
└── docker-compose.yml # 本地开发环境
七、总结
GitHub Actions 让部署从”体力活”变成了”配置活”。掌握它之后,你可以:
✅ 节省时间:一次配置,永久自动部署
✅ 减少错误:消除手动操作的人为失误
✅ 快速回滚:出问题直接revert代码即可
✅ 团队协作:所有人都能看到部署状态
建议下一步:
1. 先从一个简单的静态站点开始实践
2. 逐步添加测试、缓存等优化
3. 最后应用到生产环境
关于作者
长期关注大模型应用落地与云服务器实战,专注技术在企业场景中的落地实践。
个人博客:y1cloud.cn —— 持续更新云计算、AI大模型实战教程,欢迎访问交流。
