适用人群:后端开发者、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可以并行
✅ 通知:构建失败时通知团队
学习建议
- 先配置基本的CI,每次提交自动运行测试
- 学习GitHub Actions,最流行的CI/CD工具
- 配置自动部署,减少手动操作
- 管理好密钥,安全第一
- 监控构建状态,及时发现问题