CI/CD 持续集成教程 — 自动化部署必备

适用人群:后端开发者、DevOps工程师
学习时长:约1-2天
工具:GitHub Actions / GitLab CI / Jenkins
重要程度:★★★★☆(现代开发必备)

一、CI/CD 是什么?

概念说明
CI(持续集成)代码提交后自动运行测试、构建
CD(持续部署)测试通过后自动部署到服务器
CD(持续交付)随时可以部署到生产环境

二、GitHub Actions

2.1 基本配置

# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

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 tests
        run: npm test
        
      - name: Run lint
        run: npm run lint

2.2 Python项目

name: Python CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'
          
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
          pip install pytest
          
      - name: Run tests
        run: pytest

2.3 PHP项目

name: PHP CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
          extensions: mbstring, xml, ctype, json, bcmath, pdo, mysql
          
      - name: Install dependencies
        run: composer install --no-progress --prefer-dist
        
      - name: Run tests
        run: php artisan test

2.4 Go项目

name: Go CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.22'
          
      - name: Build
        run: go build -v ./...
        
      - name: Test
        run: go test -v ./...

2.5 Java项目

name: Java CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'
          
      - name: Build with Maven
        run: mvn -B package --file pom.xml
        
      - name: Run tests
        run: mvn test


三、自动部署

3.1 部署到服务器

name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    needs: test  # 依赖测试job
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup SSH
        uses: webfactory/ssh-agent@v0.9.0
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
      
      - name: Deploy to server
        run: |
          ssh -o StrictHostKeyChecking=no user@server << 'EOF'
            cd /var/www/myapp
            git pull origin main
            composer install --no-dev --optimize-autoloader
            php artisan migrate --force
            php artisan config:cache
            php artisan route:cache
            sudo systemctl restart php8.2-fpm
          EOF

3.2 Docker部署

name: Docker Deploy

on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: ${{ secrets.DOCKER_USERNAME }}/myapp:latest
      
      - name: Deploy to server
        run: |
          ssh user@server "docker pull ${{ secrets.DOCKER_USERNAME }}/myapp:latest && docker-compose up -d"

3.3 部署到宝塔面板

name: Deploy to BT Panel

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup SSH
        uses: webfactory/ssh-agent@v0.9.0
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
      
      - name: Deploy
        run: |
          ssh -o StrictHostKeyChecking=no root@server << 'EOF'
            cd /www/wwwroot/myapp
            git pull origin main
            composer install --no-dev
            php artisan migrate --force
            php artisan config:cache
            php artisan route:cache
            php artisan view:cache
            sudo chown -R www:www /www/wwwroot/myapp
            sudo systemctl restart php-fpm
            sudo systemctl restart nginx
          EOF


四、GitLab CI

# .gitlab-ci.yml
stages:
  - test
  - build
  - deploy

variables:
  MYSQL_DATABASE: test_db
  MYSQL_ROOT_PASSWORD: password

test:
  stage: test
  image: node:20
  services:
    - mysql:8.0
  script:
    - npm ci
    - npm test
  only:
    - main
    - develop

build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t myapp:$CI_COMMIT_SHA .
    - docker tag myapp:$CI_COMMIT_SHA registry.example.com/myapp:latest
    - docker push registry.example.com/myapp:latest
  only:
    - main

deploy:
  stage: deploy
  image: alpine:latest
  before_script:
    - apk add --no-cache openssh-client
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | ssh-add -
  script:
    - ssh -o StrictHostKeyChecking=no user@server "docker pull registry.example.com/myapp:latest && docker-compose up -d"
  only:
    - main
  when: manual


五、环境变量与密钥管理

5.1 GitHub Secrets

Settings → Secrets and variables → Actions → New repository secret

常用密钥:
- SSH_PRIVATE_KEY:SSH私钥
- DOCKER_USERNAME:Docker Hub用户名
- DOCKER_PASSWORD:Docker Hub密码
- DATABASE_URL:数据库连接字符串
- API_KEY:第三方API密钥

5.2 使用密钥

steps:
  - name: Use secrets
    run: echo "Deploying..."
    env:
      DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
      API_KEY: ${{ secrets.API_KEY }}


六、最佳实践

✅ 每次提交都运行测试
✅ 分支保护:main分支需要PR和Review
✅ 自动化部署:测试通过后自动部署到staging
✅ 手动部署生产:生产环境需要手动确认
✅ 密钥管理:使用Secrets,不要硬编码
✅ 构建缓存:缓存依赖加快构建速度
✅ 并行执行:测试和Lint可以并行
✅ 通知:构建失败时通知团队


学习建议

  1. 先配置基本的CI,每次提交自动运行测试
  2. 学习GitHub Actions,最流行的CI/CD工具
  3. 配置自动部署,减少手动操作
  4. 管理好密钥,安全第一
  5. 监控构建状态,及时发现问题
返回首页