Docker 化的 CI/CD 流水线
使用 GitHub Actions + Docker 构建一个完整的自动化测试、构建、部署流水线
你将学到
- 使用 GitHub Actions 定义 CI/CD 流水线
- 自动化构建和推送 Docker 镜像
- 实现自动化测试和部署
- 管理环境变量和密钥
前置知识
架构设计
代码推送 → GitHub Actions → 构建镜像 → 推送仓库 → 部署服务器
│ │ │ │ │
└────────────┴──────────────┴───────────┴───────────┘
自动化流水线
实现步骤
第一步:项目结构
myapp/
├── .github/
│ └── workflows/
│ └── ci.yml
├── Dockerfile
├── docker-compose.yml
├── app/
└── tests/
第二步:Dockerfile(多阶段)
# Dockerfile
# 测试阶段
FROM python:3.11-slim AS test
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN pytest tests/ -v
# 构建阶段
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
# 生产阶段
FROM python:3.11-slim AS production
RUN groupadd -r appuser && useradd -r -g appuser appuser
WORKDIR /app
COPY --from=builder /root/.local /home/appuser/.local
COPY --chown=appuser:appuser . .
USER appuser
ENV PATH=/home/appuser/.local/bin:$PATH
EXPOSE 8000
HEALTHCHECK CMD curl -f http://localhost:8000/health || exit 1
CMD ["python", "app.py"]
第三步:GitHub Actions 配置
# .github/workflows/ci.yml
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
run: |
docker build --target test -t myapp:test .
docker run --rm myapp:test
build:
needs: test
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha
type=raw,value=latest
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
deploy:
needs: build
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Deploy to server
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_KEY }}
script: |
cd /opt/myapp
docker compose pull
docker compose up -d
第四步:Docker Compose(部署用)
# docker-compose.yml
version: "3.8"
services:
app:
image: ghcr.io/username/myapp:latest
ports:
- "8000:8000"
environment:
- DATABASE_URL=${DATABASE_URL}
- REDIS_URL=${REDIS_URL}
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 3s
retries: 3
第五步:环境变量和密钥管理
# GitHub Secrets 配置
# Settings → Secrets and variables → Actions
# 必需的密钥:
# - SERVER_HOST: 服务器地址
# - SERVER_USER: 服务器用户名
# - SERVER_KEY: SSH 私钥
# - DATABASE_URL: 数据库连接字符串
# - REDIS_URL: Redis 连接字符串
完整项目结构
myapp/
├── .github/
│ └── workflows/
│ └── ci.yml # CI/CD 流水线定义
├── Dockerfile # 多阶段构建
├── docker-compose.yml # 部署配置
├── app/
│ └── app.py # 应用代码
├── tests/
│ └── test_app.py # 测试代码
└── requirements.txt
最佳实践
- 多阶段构建:测试、构建、生产分离
- 自动化测试:每次提交都运行测试
- 镜像标签:使用 Git SHA 作为镜像标签
- 密钥管理:使用 GitHub Secrets 存储敏感信息
- 健康检查:确保部署后服务可用
常见问题
Q: 如何回滚部署? A: 使用之前的镜像标签重新部署。
Q: 如何查看部署日志? A: 在 GitHub Actions 页面查看工作流日志。
Q: 如何支持多环境部署? A: 使用 GitHub Environments 管理不同环境。
扩展挑战
- 添加 Slack/钉钉通知
- 实现蓝绿部署
- 添加自动回滚机制
相关课程
| 课程 | 相关章节 |
|---|---|
| Docker | CI/CD 与 Docker |
| Docker | 多阶段构建 |
| Docker | 镜像仓库 |
| Docker | Docker Compose |