预计时间
1 周
学习目标
- 掌握 GitHub Actions 工作流
- 实现 Push → Build → Test → Deploy 自动化
- 理解滚动更新 vs 蓝绿部署
一、没有 CI/CD 的痛
text
手动部署流程:
1. 本地改代码
2. npm run build
3. docker build -t my-app:v1.2.3 .
4. docker push my-registry/my-app:v1.2.3
5. SSH 到服务器
6. docker pull my-registry/my-app:v1.2.3
7. docker compose down && docker compose up -d
8. 忘了跑测试 → 线上崩了
9. 忘了改环境变量 → 连不上数据库
10. 客户打电话过来 → 回滚 → 不记得上一个版本号
有 CI/CD:
git push → 自动构建 → 自动测试 → 自动部署 → Slack 通知
出问题 → 一键回滚二、GitHub Actions 基础
2.1 工作流文件
yaml
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main] # main 分支 push 时触发
pull_request:
branches: [main] # PR 到 main 也触发(只跑测试)
env:
NODE_VERSION: '20'
REGISTRY: ghcr.io # GitHub Container Registry
IMAGE_NAME: ${{ github.repository }}
jobs:
# ===== Job 1: 测试 =====
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run test
# ===== Job 2: 构建镜像 =====
build:
needs: test # 等 test 过了才构建
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: |
docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest .
docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} .
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push Docker image
run: docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} --all-tags
# ===== Job 3: 部署 =====
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' # 只有 main 分支才部署
steps:
- name: Deploy to server
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: |
cd /app
docker compose pull
docker compose up -d --remove-orphans
docker image prune -f2.2 关键概念
text
Workflow: 整个自动化流程(.github/workflows/xxx.yml)
Job: 一个独立执行的任务(在独立 VM 上跑)
Step: Job 中的每个步骤
Action: 可复用的步骤(如 actions/checkout、setup-node)
触发器:
on: push → 代码推送到仓库
on: pull_request → 创建 PR
on: schedule → 定时(cron)
on: workflow_dispatch → 手动触发三、环境与密钥管理
yaml
# 密钥在 GitHub → Settings → Secrets and variables → Actions 中配置
# 代码中用 ${{ secrets.XXX }} 引用,不会暴露
# 分环境部署
deploy-staging:
if: github.ref == 'refs/heads/develop'
environment: staging
steps:
- run: deploy to staging server
deploy-production:
if: github.ref == 'refs/heads/main'
environment: production
steps:
- run: deploy to production servertext
GitHub Environments:
可以设置环境专属的 Secrets
可以设置保护规则(如部署前需要 reviewer 审批)
production 环境可以设:必须某人 approve 才能部署四、部署策略
4.1 滚动更新(最常用)
yaml
# docker compose 中
deploy:
replicas: 3
update_config:
parallelism: 1 # 一次更新 1 个
delay: 10s # 间隔 10 秒
order: start-first # 先启动新的,再停旧的text
过程:
1. 启动新容器 v2
2. 等 v2 健康检查通过
3. 停掉一个 v1
4. 重复 → 直到全部替换
优点:服务不中断
缺点:更新过程中新旧版本共存,兼容性要注意4.2 蓝绿部署
text
蓝环境(当前 v1)在跑 → 部署 v2 到另一个环境(绿)
验证绿环境没问题 → 一键切流量到绿
出问题 → 切回蓝
优点:回滚最快(秒级)
缺点:需要双倍资源4.3 金丝雀发布
text
v2 先放给 5% 用户 → 观察 → 放给 25% → 观察 → 放给 100%
优点:渐进式验证,影响面小
缺点:需要流量控制基础设施五、完整 CI/CD Pipeline
text
git push (main)
↓
┌──── Job: test ──────┐
│ npm ci │
│ npm run lint │
│ npm run test │
└─────────────────────┘
↓ 通过
┌──── Job: build ─────┐
│ docker build │
│ tag: latest + sha │
│ push to registry │
└─────────────────────┘
↓
┌──── Job: deploy ────┐
│ SSH to server │
│ docker pull │
│ docker up -d │
│ health check │
└─────────────────────┘
↓
Slack 通知实践
- 创建
.github/workflows/deploy.yml - 在 GitHub 仓库 Settings 中配置 Secrets
- 推代码到 main → 观察 Actions 面板
- 故意写个失败的测试 → 观察 Pipeline 中断
- 设置
environment: production+ 审批规则