⚙️ 第四课:CI/CD 自动化部署流水线

预计阅读时间:14 分钟  |  难度:进阶 ⭐⭐⭐

📋 本课目标:理解 CI/CD 的核心流程,能使用 GitHub Actions 搭建一条完整的自动化流水线——每次 git push 后自动构建、测试、部署到服务器。并了解蓝绿部署和回滚策略。

1 为什么需要 CI/CD?

前两课我们实践了两种部署方式,但都有一个共同的问题:每次更新都要手动操作

手工部署的工作流:

git push → SSH 连服务器 → git pull → npm install → npm run build → pm2 restart → 完成

这里面每一步都可能出错(忘拉代码、用了旧依赖、端口冲突……)。而且当你需要频繁更新(一天多次)时,手工操作的时间成本不可忽视。

CI/CD 的目标:把上述流程自动化。你只做 git push,剩下的交给流水线。

✏️ 编码 ⬆️ git push 🧪 自动测试 📦 自动构建 🚀 自动部署 📊 健康检查

2 CI/CD 核心概念

概念做什么交付物
CI(持续集成)频繁合并代码到主分支 → 自动运行测试和构建一个通过测试的构建产物
CD(持续部署)将通过 CI 的产物自动部署到生产环境线上可访问的服务
CD(持续交付)产物通过 CI 后自动准备好,但需要手动确认才部署到生产一个"一键部署"的待命版本

简单来说:CI = 自动检查代码质量,CD = 自动把代码送上线

3 GitHub Actions 实战:从零搭建流水线

GitHub Actions 是目前最流行的 CI/CD 平台之一(与 GitHub 仓库原生集成,无需额外配置)。

3.1 基本概念

术语说明类比
Workflow一个完整的自动化流程,定义在 .github/workflows/*.yml工厂的生产线
JobWorkflow 中的一个任务单元。多个 Job 可以并行或串行执行生产线上的一个工位
StepJob 中的单个操作(运行命令或调用 Action)工位上的一个操作
Action可复用的 GitHub Actions 模块(社区或官方提供)预制工具(扳手、螺丝刀)
Runner运行 Workflow 的服务器(GitHub 托管或自托管)工厂车间

3.2 编写第一个 Workflow

在仓库中创建 .github/workflows/deploy.yml

# .github/workflows/deploy.yml
name: Deploy to Production

# 触发条件:push 到 master/main 分支
on:
  push:
    branches: [main]
  # 也可以手动触发
  workflow_dispatch:

jobs:
  # Job 1:CI — 构建和测试
  ci:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 18

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test

      - name: Build
        run: npm run build

      # 保存构建产物,供后续 Job 使用
      - name: Upload build artifact
        uses: actions/upload-artifact@v4
        with:
          name: build-output
          path: dist/

  # Job 2:CD — 部署到服务器(等 CI 完成后再执行)
  deploy:
    needs: ci # 等 ci job 成功后执行
    runs-on: ubuntu-latest
    steps:
      - name: Download build artifact
        uses: actions/download-artifact@v4
        with:
          name: build-output
          path: dist/

      - name: Deploy via SSH
        uses: appleboy/scp-action@v0.1.7
        with:
          host: ${{ secrets.DEPLOY_HOST }}
          username: ${{ secrets.DEPLOY_USER }}
          key: ${{ secrets.DEPLOY_KEY }}
          source: "dist/"
          target: "/var/www/myapp/"

      - name: Restart application
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.DEPLOY_HOST }}
          username: ${{ secrets.DEPLOY_USER }}
          key: ${{ secrets.DEPLOY_KEY }}
          script: |
            cd /var/www/myapp
            docker compose pull
            docker compose up -d --build

3.3 配置 Secrets(敏感信息)

上面的 workflow 中使用了 ${{ secrets.XXX }},这些值绝对不能写在代码里。

在 GitHub 仓库页面设置:

# Settings → Secrets and variables → Actions → New repository secret

DEPLOY_HOST → 你的服务器 IP(如 123.123.123.123)
DEPLOY_USER → 登录用户名(如 ubuntu)
DEPLOY_KEY → SSH 私钥的全部内容(cat ~/.ssh/id_ed25519)
# 如果还需要其他敏感信息也放这里
DB_PASSWORD → 数据库密码
⚠️ 安全警告:永远不要在 workflow 文件中硬编码密码、密钥、令牌。使用 GitHub Secrets。
另外:用于部署的 SSH 密钥不要设置密码短语(passphrase),否则 CI 在运行时会卡住等待输入。
参考:GitHub Actions Secrets 文档

4 Docker + CI/CD = 完美组合

将 Docker 与 CI/CD 结合是最常见的生产模式:

# .github/workflows/docker-deploy.yml 片段

jobs:
  build-and-push:
    steps:
      # ... checkout、test ...

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: ${{ secrets.DOCKER_USERNAME }}/myapp:latest

  deploy:
    needs: build-and-push
    steps:
      - name: SSH and deploy
        uses: appleboy/ssh-action@v1.0.3
        with:
          script: |
            docker pull myuser/myapp:latest
            docker compose up -d --build

Docker 版本对比直接传文件的优势:服务器上不需要安装 Node.js 等运行时——Docker 镜像已经包含了所有依赖。服务器只需要 Docker 引擎。

5 蓝绿部署与回滚策略

🌊 蓝绿部署(Blue-Green Deployment)

核心思路:准备两套完全一样的环境(蓝/绿),只有一套对外服务:

Nginx 实现蓝绿切换的配置示意:

# 蓝绿切换:编辑 Nginx upstream,重载即可
upstream myapp {
  # server 127.0.0.1:3001; # 蓝色(旧版,暂不启用)
  server 127.0.0.1:3002;  # 绿色(新版,当前活跃)
}

server {
  listen 80;
  server_name example.com;
  location / {
    proxy_pass http://myapp;
  }
}

5.1 回滚策略

自动化部署必须配套自动回滚能力:

部署方式回滚方法
传统部署(文件)保留前 N 个版本的备份目录,重新软链接即可回滚
Docker 部署使用版本标签(如 myapp:v1.2.3),回滚时改 tag 重新部署
蓝绿部署流量切回旧环境,一键完成

6 PaaS:另一种"自动化"思路

如果你不想自己维护 CI/CD 基础设施,也可以选择 PaaS(平台即服务)——代码推上去,平台帮你运行:

平台特点适合场景
Vercel前端/全栈(Next.js 亲爹),自动 HTTPS 和 CDN前端项目、Next.js 应用
Railway极简部署体验,支持多种语言和数据库全栈项目快速部署
Fly.io边缘部署,全球多节点需要低延迟的全球应用
HerokuPaaS 老牌标杆,生态完善传统 Web 应用(但免费方案已取消)
💡 建议学习方法:先用传统手工部署理解底层(第二课),然后用 Docker 提高效率(第三课),最后用 CI/CD 彻底解放双手(第四课)。这三层递进,每一层都让你更理解下一层的价值。

7 小测验

Q1: GitHub Actions 中,如何确保 deploy job 在 ci job 成功后才执行?

Q2: 如何在 GitHub Actions 中安全使用服务器密码和密钥?

Q3: 蓝绿部署相比直接部署的最大优势是什么?

📖 推荐官方文档

📌 第五课预告

第五课:生产环境安全加固与运维

部署上线只是开始。这一课覆盖生产环境必须做的安全措施——防火墙深度配置、备份策略、监控告警、日志管理,以及灾难恢复计划。