Skip to content

4.7 Docker和持续集成

🎯 学习目标:掌握MCP服务器的容器化开发和CI/CD流水线,实现自动化开发工作流
⏱️ 预计时间:35分钟
📊 难度等级:⭐⭐⭐

🐳 为什么选择Docker?

在现代软件开发中,"在我机器上能运行"已经不是借口了!Docker让我们能够:

  • 🎯 环境一致性:开发、测试、生产环境完全一致
  • 🚀 快速部署:一键启动完整的应用栈
  • 📦 依赖隔离:不会与宿主机的其他应用冲突
  • 🔄 易于扩展:轻松实现水平扩展和负载均衡

🛠️ 开发环境Docker配置

📋 开发用Dockerfile

创建 Dockerfile.dev

dockerfile
# Dockerfile.dev - 开发环境专用
FROM python:3.11-slim

# 设置标签
LABEL maintainer="developer@example.com"
LABEL description="MCP Server - 开发环境"
LABEL stage="development"

# 安装开发工具
RUN apt-get update && apt-get install -y \
    git \
    curl \
    wget \
    vim \
    htop \
    tree \
    jq \
    && rm -rf /var/lib/apt/lists/*

# 设置工作目录
WORKDIR /app

# 设置开发环境变量
ENV PYTHONPATH=/app \
    PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    MCP_ENV=development \
    MCP_LOG_LEVEL=DEBUG \
    MCP_DEBUG=true

# 安装Python开发依赖
COPY requirements.txt requirements-dev.txt ./
RUN pip install --upgrade pip && \
    pip install -r requirements.txt && \
    pip install -r requirements-dev.txt

# 创建开发用的非root用户
RUN groupadd -r developer && \
    useradd -r -g developer developer && \
    chown -R developer:developer /app

# 复制源代码(开发模式下通过volume挂载)
COPY . .

# 设置权限
RUN chown -R developer:developer /app

# 切换到开发用户
USER developer

# 暴露调试端口
EXPOSE 8000 5678

# 开发模式启动命令(支持代码热重载)
CMD ["python", "-m", "debugpy", "--listen", "0.0.0.0:5678", "--wait-for-client", "server.py"]

🔧 开发环境依赖

创建 requirements-dev.txt

txt
# requirements-dev.txt - 开发环境专用依赖

# 代码质量工具
black==23.12.1              # 代码格式化
isort==5.13.2               # 导入排序
flake8==7.0.0               # 代码检查
mypy==1.8.0                 # 类型检查
pylint==3.0.3               # 代码质量检查

# 测试工具
pytest==7.4.4              # 测试框架
pytest-asyncio==0.23.2     # 异步测试支持
pytest-cov==4.1.0          # 测试覆盖率
pytest-mock==3.12.0        # Mock工具
pytest-xdist==3.5.0        # 并行测试
faker==22.1.0               # 测试数据生成

# 调试工具
debugpy==1.8.0             # VS Code调试支持
ipdb==0.13.13               # 调试器
memory-profiler==0.61.0     # 内存分析
line-profiler==4.1.1        # 性能分析

# 文档工具
sphinx==7.2.6              # 文档生成
sphinx-rtd-theme==2.0.0     # 文档主题

# 开发实用工具
pre-commit==3.6.0           # Git钩子
tox==4.11.4                 # 多环境测试
watchdog==3.0.0             # 文件变化监控
rich==13.7.0                # 美化终端输出

🐳 开发环境Docker Compose

创建 docker-compose.dev.yml

yaml
# docker-compose.dev.yml - 开发环境配置
version: '3.8'

services:
  mcp-server-dev:
    build:
      context: .
      dockerfile: Dockerfile.dev
    container_name: mcp-server-dev
    restart: unless-stopped
    ports:
      - "8000:8000"    # 应用端口
      - "5678:5678"    # 调试端口
      - "9090:9090"    # 监控端口
    environment:
      - MCP_ENV=development
      - MCP_LOG_LEVEL=DEBUG
      - MCP_DEBUG=true
      - MCP_REDIS_URL=redis://redis-dev:6379/0
      - PYTHONPATH=/app
    volumes:
      # 挂载源代码实现热重载
      - .:/app
      - /app/__pycache__  # 排除缓存目录
      - /app/.pytest_cache
      - dev-logs:/app/logs
    depends_on:
      - redis-dev
      - postgres-dev
    networks:
      - mcp-dev-network
    stdin_open: true
    tty: true
    command: >
      sh -c "
        echo '🚀 启动开发环境...'
        python -m pytest tests/ --tb=short -q &&
        echo '✅ 测试通过,启动服务器...' &&
        python server.py
      "

  redis-dev:
    image: redis:7-alpine
    container_name: mcp-redis-dev
    restart: unless-stopped
    ports:
      - "6379:6379"
    volumes:
      - redis-dev-data:/data
    networks:
      - mcp-dev-network
    command: redis-server --appendonly yes --maxmemory 128mb

  postgres-dev:
    image: postgres:15-alpine
    container_name: mcp-postgres-dev
    restart: unless-stopped
    ports:
      - "5432:5432"
    environment:
      POSTGRES_DB: mcp_dev
      POSTGRES_USER: mcp_user
      POSTGRES_PASSWORD: mcp_pass
    volumes:
      - postgres-dev-data:/var/lib/postgresql/data
      - ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - mcp-dev-network

  # 开发工具容器
  dev-tools:
    build:
      context: .
      dockerfile: Dockerfile.dev
    container_name: mcp-dev-tools
    volumes:
      - .:/app
    networks:
      - mcp-dev-network
    profiles:
      - tools
    command: tail -f /dev/null  # 保持容器运行

volumes:
  redis-dev-data:
  postgres-dev-data:
  dev-logs:

networks:
  mcp-dev-network:
    driver: bridge

🔄 GitHub Actions CI/CD流水线

🚀 主要工作流

创建 .github/workflows/ci-cd.yml

yaml
# .github/workflows/ci-cd.yml
name: MCP Server CI/CD

on:
  push:
    branches: [ main, develop ]
    tags: [ 'v*' ]
  pull_request:
    branches: [ main, develop ]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  # 代码质量检查
  code-quality:
    name: 代码质量检查
    runs-on: ubuntu-latest
    steps:
      - name: 检出代码
        uses: actions/checkout@v4

      - name: 设置Python环境
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
          cache: 'pip'

      - name: 安装依赖
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt -r requirements-dev.txt

      - name: 代码格式检查 (Black)
        run: black --check --diff .

      - name: 导入排序检查 (isort)
        run: isort --check-only --diff .

      - name: 代码风格检查 (flake8)
        run: flake8 . --count --statistics

      - name: 类型检查 (MyPy)
        run: mypy . --ignore-missing-imports

      - name: 安全检查 (Bandit)
        run: |
          pip install bandit
          bandit -r . -f json -o bandit-report.json || true

      - name: 上传安全检查报告
        uses: actions/upload-artifact@v3
        with:
          name: security-report
          path: bandit-report.json

  # 单元测试
  unit-tests:
    name: 单元测试
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ['3.10', '3.11', '3.12']

    steps:
      - name: 检出代码
        uses: actions/checkout@v4

      - name: 设置Python ${{ matrix.python-version }}
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}
          cache: 'pip'

      - name: 安装依赖
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt -r requirements-dev.txt

      - name: 运行单元测试
        run: |
          python -m pytest tests/ \
            --cov=. \
            --cov-report=xml \
            --cov-report=html \
            --junit-xml=test-results.xml \
            -v

      - name: 上传测试结果
        uses: actions/upload-artifact@v3
        if: always()
        with:
          name: test-results-py${{ matrix.python-version }}
          path: |
            test-results.xml
            htmlcov/
            .coverage

      - name: 上传覆盖率到Codecov
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage.xml
          flags: unittests
          name: codecov-py${{ matrix.python-version }}

  # 集成测试
  integration-tests:
    name: 集成测试
    runs-on: ubuntu-latest
    needs: [code-quality, unit-tests]
    
    services:
      redis:
        image: redis:7-alpine
        ports:
          - 6379:6379
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

      postgres:
        image: postgres:15
        ports:
          - 5432:5432
        env:
          POSTGRES_PASSWORD: test_password
          POSTGRES_DB: test_db
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - name: 检出代码
        uses: actions/checkout@v4

      - name: 设置Python环境
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
          cache: 'pip'

      - name: 安装依赖
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt -r requirements-dev.txt

      - name: 等待服务就绪
        run: |
          sleep 10
          redis-cli -h localhost -p 6379 ping
          pg_isready -h localhost -p 5432

      - name: 运行集成测试
        env:
          MCP_REDIS_URL: redis://localhost:6379/0
          MCP_DATABASE_URL: postgresql://postgres:test_password@localhost:5432/test_db
        run: |
          python -m pytest tests/integration/ -v \
            --junit-xml=integration-test-results.xml

      - name: 上传集成测试结果
        uses: actions/upload-artifact@v3
        if: always()
        with:
          name: integration-test-results
          path: integration-test-results.xml

  # Docker镜像构建
  build-image:
    name: 构建Docker镜像
    runs-on: ubuntu-latest
    needs: [code-quality, unit-tests]
    outputs:
      image-digest: ${{ steps.build.outputs.digest }}
      image-tag: ${{ steps.meta.outputs.tags }}

    steps:
      - name: 检出代码
        uses: actions/checkout@v4

      - name: 设置Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: 登录到容器注册表
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: 提取元数据
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=raw,value=latest,enable={{is_default_branch}}

      - name: 构建并推送镜像
        id: build
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          build-args: |
            VERSION=${{ github.ref_name }}
            BUILD_DATE=${{ steps.meta.outputs.created }}
            VCS_REF=${{ github.sha }}

  # 安全扫描
  security-scan:
    name: 安全扫描
    runs-on: ubuntu-latest
    needs: [build-image]
    if: github.event_name != 'pull_request'

    steps:
      - name: 运行Trivy漏洞扫描
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: ${{ needs.build-image.outputs.image-tag }}
          format: 'sarif'
          output: 'trivy-results.sarif'

      - name: 上传扫描结果到GitHub Security
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: 'trivy-results.sarif'

  # 部署到测试环境
  deploy-staging:
    name: 部署到测试环境
    runs-on: ubuntu-latest
    needs: [integration-tests, build-image, security-scan]
    if: github.ref == 'refs/heads/develop'
    environment: staging

    steps:
      - name: 检出代码
        uses: actions/checkout@v4

      - name: 设置kubectl
        uses: azure/setup-kubectl@v3
        with:
          version: 'v1.28.0'

      - name: 配置Kubernetes访问
        run: |
          echo "${{ secrets.KUBE_CONFIG_STAGING }}" | base64 -d > kubeconfig
          export KUBECONFIG=kubeconfig

      - name: 部署到测试环境
        run: |
          kubectl set image deployment/mcp-server \
            mcp-server=${{ needs.build-image.outputs.image-tag }} \
            -n staging
          
          kubectl rollout status deployment/mcp-server -n staging

      - name: 运行部署后测试
        run: |
          sleep 30
          kubectl port-forward service/mcp-server 8080:8000 -n staging &
          sleep 5
          
          # 健康检查
          curl -f http://localhost:8080/health || exit 1
          
          # API测试
          python scripts/integration_test.py --url http://localhost:8080

  # 部署到生产环境
  deploy-production:
    name: 部署到生产环境
    runs-on: ubuntu-latest
    needs: [integration-tests, build-image, security-scan]
    if: startsWith(github.ref, 'refs/tags/v')
    environment: production

    steps:
      - name: 检出代码
        uses: actions/checkout@v4

      - name: 设置kubectl
        uses: azure/setup-kubectl@v3
        with:
          version: 'v1.28.0'

      - name: 配置Kubernetes访问
        run: |
          echo "${{ secrets.KUBE_CONFIG_PRODUCTION }}" | base64 -d > kubeconfig
          export KUBECONFIG=kubeconfig

      - name: 蓝绿部署到生产环境
        run: |
          # 部署到绿色环境
          kubectl set image deployment/mcp-server-green \
            mcp-server=${{ needs.build-image.outputs.image-tag }} \
            -n production
          
          kubectl rollout status deployment/mcp-server-green -n production
          
          # 验证绿色环境
          kubectl port-forward service/mcp-server-green 8081:8000 -n production &
          sleep 10
          curl -f http://localhost:8081/health || exit 1
          
          # 切换流量
          kubectl patch service mcp-server \
            -p '{"spec":{"selector":{"version":"green"}}}' \
            -n production

      - name: 发布通知
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          text: "🚀 MCP Server ${{ github.ref_name }} 已成功部署到生产环境!"
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

🔧 Pre-commit钩子配置

创建 .pre-commit-config.yaml

yaml
# .pre-commit-config.yaml
repos:
  # Python代码格式化
  - repo: https://github.com/psf/black
    rev: 23.12.1
    hooks:
      - id: black
        language_version: python3.11

  # 导入排序
  - repo: https://github.com/pycqa/isort
    rev: 5.13.2
    hooks:
      - id: isort
        args: ["--profile", "black"]

  # 代码质量检查
  - repo: https://github.com/pycqa/flake8
    rev: 7.0.0
    hooks:
      - id: flake8
        additional_dependencies: [flake8-docstrings]

  # 安全检查
  - repo: https://github.com/pycqa/bandit
    rev: 1.7.5
    hooks:
      - id: bandit
        args: ["-c", "pyproject.toml"]

  # YAML格式检查
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: check-yaml
      - id: check-json
      - id: check-toml
      - id: end-of-file-fixer
      - id: trailing-whitespace
      - id: check-merge-conflict
      - id: check-added-large-files

  # Docker相关检查
  - repo: https://github.com/hadolint/hadolint
    rev: v2.12.0
    hooks:
      - id: hadolint-docker
        args: ["--ignore", "DL3008", "--ignore", "DL3009"]

  # 提交信息格式检查
  - repo: https://github.com/commitizen-tools/commitizen
    rev: v3.13.0
    hooks:
      - id: commitizen
        stages: [commit-msg]

📊 测试配置优化

创建 pytest.ini(增强版):

ini
[tool:pytest]
# 测试发现
testpaths = tests
python_files = test_*.py *_test.py
python_classes = Test*
python_functions = test_*

# 输出配置
addopts = 
    -ra                     # 显示所有测试结果摘要
    -v                      # 详细输出
    --tb=short             # 简短错误追踪
    --strict-markers       # 严格标记模式
    --strict-config        # 严格配置检查
    --color=yes           # 彩色输出
    --durations=10        # 显示最慢的10个测试
    --cov=.               # 代码覆盖率
    --cov-report=term-missing  # 终端覆盖率报告
    --cov-report=html:htmlcov  # HTML覆盖率报告
    --cov-report=xml      # XML覆盖率报告
    --cov-fail-under=80   # 覆盖率阈值
    --maxfail=3           # 最多失败3个测试后停止
    --disable-warnings    # 禁用警告显示

# 测试标记
markers =
    unit: 单元测试
    integration: 集成测试
    e2e: 端到端测试
    slow: 慢速测试(>5秒)
    fast: 快速测试(<1秒)
    network: 需要网络连接
    database: 需要数据库连接
    redis: 需要Redis连接
    security: 安全相关测试
    performance: 性能测试
    smoke: 冒烟测试

# 过滤警告
filterwarnings =
    ignore::DeprecationWarning
    ignore::PendingDeprecationWarning
    ignore::UserWarning:requests.*

# 异步测试配置
asyncio_mode = auto
timeout = 300

# 并行测试配置
addopts = -n auto --dist=worksteal

# 覆盖率配置
[coverage:run]
source = .
omit = 
    */tests/*
    */venv/*
    */env/*
    setup.py
    conftest.py
    */migrations/*
    */__pycache__/*

[coverage:report]
exclude_lines =
    pragma: no cover
    def __repr__
    if self.debug:
    if settings.DEBUG
    raise AssertionError
    raise NotImplementedError
    if 0:
    if __name__ == .__main__.:
    class .*\bProtocol\):
    @(abc\.)?abstractmethod

🚀 开发工作流脚本

🛠️ 开发环境启动脚本

创建 scripts/dev-setup.sh

bash
#!/bin/bash
# scripts/dev-setup.sh - 开发环境设置脚本

set -e

# 颜色定义
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'

echo -e "${BLUE}🚀 MCP Server 开发环境设置${NC}"
echo "================================"

# 检查Docker和Docker Compose
if ! command -v docker &> /dev/null; then
    echo -e "${RED}❌ Docker未安装,请先安装Docker${NC}"
    exit 1
fi

if ! command -v docker-compose &> /dev/null; then
    echo -e "${RED}❌ Docker Compose未安装,请先安装Docker Compose${NC}"
    exit 1
fi

# 检查.env文件
if [ ! -f ".env.dev" ]; then
    echo -e "${YELLOW}⚠️  创建开发环境配置文件${NC}"
    cat > .env.dev << 'EOF'
# 开发环境配置
MCP_ENV=development
MCP_LOG_LEVEL=DEBUG
MCP_DEBUG=true
MCP_REDIS_URL=redis://redis-dev:6379/0
MCP_DATABASE_URL=postgresql://mcp_user:mcp_pass@postgres-dev:5432/mcp_dev

# 监控配置
MCP_PROMETHEUS_ENABLED=true
MCP_PROMETHEUS_PORT=9090

# 开发工具配置
PYTHONPATH=/app
PYTHONUNBUFFERED=1
PYTHONDONTWRITEBYTECODE=1
EOF
    echo -e "${GREEN}✅ 开发环境配置文件已创建${NC}"
fi

# 安装pre-commit钩子
if command -v pre-commit &> /dev/null; then
    echo -e "${BLUE}📋 安装pre-commit钩子${NC}"
    pre-commit install
    pre-commit install --hook-type commit-msg
    echo -e "${GREEN}✅ Pre-commit钩子已安装${NC}"
else
    echo -e "${YELLOW}⚠️  建议安装pre-commit: pip install pre-commit${NC}"
fi

# 构建开发环境
echo -e "${BLUE}🐳 构建开发环境Docker镜像${NC}"
docker-compose -f docker-compose.dev.yml build --no-cache

# 启动服务
echo -e "${BLUE}🚀 启动开发环境服务${NC}"
docker-compose -f docker-compose.dev.yml up -d

# 等待服务就绪
echo -e "${BLUE}⏳ 等待服务启动...${NC}"
sleep 15

# 检查服务状态
echo -e "${BLUE}🔍 检查服务状态${NC}"
docker-compose -f docker-compose.dev.yml ps

# 运行初始测试
echo -e "${BLUE}🧪 运行初始测试${NC}"
docker-compose -f docker-compose.dev.yml exec -T mcp-server-dev python -m pytest tests/ --tb=short -q

echo ""
echo -e "${GREEN}🎉 开发环境设置完成!${NC}"
echo ""
echo "📋 可用命令:"
echo "  🐳 查看日志: docker-compose -f docker-compose.dev.yml logs -f"
echo "  🧪 运行测试: docker-compose -f docker-compose.dev.yml exec mcp-server-dev python -m pytest"
echo "  🔧 进入容器: docker-compose -f docker-compose.dev.yml exec mcp-server-dev bash"
echo "  📊 查看监控: http://localhost:9090"
echo "  🛑 停止服务: docker-compose -f docker-compose.dev.yml down"
echo ""
echo -e "${BLUE}Happy coding! 🎯${NC}"

🧪 测试运行脚本

创建 scripts/run-tests.sh

bash
#!/bin/bash
# scripts/run-tests.sh - 测试运行脚本

set -e

# 参数解析
TEST_TYPE=${1:-all}
ENVIRONMENT=${2:-dev}

echo "🧪 运行MCP Server测试套件"
echo "测试类型: $TEST_TYPE"
echo "环境: $ENVIRONMENT"
echo "=========================="

# 根据环境选择compose文件
if [ "$ENVIRONMENT" = "ci" ]; then
    COMPOSE_FILE="docker-compose.yml"
    SERVICE_NAME="mcp-server"
else
    COMPOSE_FILE="docker-compose.dev.yml"
    SERVICE_NAME="mcp-server-dev"
fi

# 确保服务运行
echo "🔍 检查服务状态..."
docker-compose -f $COMPOSE_FILE up -d

# 等待服务就绪
sleep 5

case $TEST_TYPE in
    "unit")
        echo "🧪 运行单元测试..."
        docker-compose -f $COMPOSE_FILE exec -T $SERVICE_NAME \
            python -m pytest tests/unit/ -v \
            --cov=. --cov-report=term --cov-report=html
        ;;
    
    "integration")
        echo "🔗 运行集成测试..."
        docker-compose -f $COMPOSE_FILE exec -T $SERVICE_NAME \
            python -m pytest tests/integration/ -v \
            --tb=short
        ;;
    
    "e2e")
        echo "🎯 运行端到端测试..."
        docker-compose -f $COMPOSE_FILE exec -T $SERVICE_NAME \
            python -m pytest tests/e2e/ -v \
            --tb=short
        ;;
    
    "performance")
        echo "⚡ 运行性能测试..."
        docker-compose -f $COMPOSE_FILE exec -T $SERVICE_NAME \
            python -m pytest tests/ -m performance -v
        ;;
    
    "security")
        echo "🔒 运行安全测试..."
        docker-compose -f $COMPOSE_FILE exec -T $SERVICE_NAME \
            python -m pytest tests/ -m security -v
        ;;
    
    "fast")
        echo "🚀 运行快速测试..."
        docker-compose -f $COMPOSE_FILE exec -T $SERVICE_NAME \
            python -m pytest tests/ -m "fast and not slow" -v \
            --tb=short
        ;;
    
    "all"|*)
        echo "🎯 运行所有测试..."
        docker-compose -f $COMPOSE_FILE exec -T $SERVICE_NAME \
            python -m pytest tests/ -v \
            --cov=. --cov-report=term --cov-report=html \
            --tb=short --durations=10
        ;;
esac

echo ""
echo "✅ 测试完成!"

# 显示覆盖率报告位置
if [ "$TEST_TYPE" = "unit" ] || [ "$TEST_TYPE" = "all" ]; then
    echo "📊 HTML覆盖率报告: htmlcov/index.html"
fi

🔨 构建脚本

创建 scripts/build.sh

bash
#!/bin/bash
# scripts/build.sh - 构建脚本

set -e

VERSION=${1:-$(git rev-parse --short HEAD)}
PUSH=${2:-false}
REGISTRY=${DOCKER_REGISTRY:-"ghcr.io/your-org"}

echo "🏗️  构建MCP Server Docker镜像"
echo "版本: $VERSION"
echo "仓库: $REGISTRY"
echo "推送: $PUSH"
echo "=========================="

# 构建镜像
echo "🐳 构建Docker镜像..."
docker build \
    --build-arg VERSION=$VERSION \
    --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
    --build-arg VCS_REF=$(git rev-parse HEAD) \
    -t mcp-server:$VERSION \
    -t mcp-server:latest \
    -t $REGISTRY/mcp-server:$VERSION \
    -t $REGISTRY/mcp-server:latest \
    .

echo "✅ 镜像构建完成"

# 运行安全扫描
if command -v trivy &> /dev/null; then
    echo "🔒 运行安全扫描..."
    trivy image --exit-code 0 --severity HIGH,CRITICAL mcp-server:$VERSION
fi

# 推送镜像
if [ "$PUSH" = "true" ]; then
    echo "📤 推送镜像到仓库..."
    docker push $REGISTRY/mcp-server:$VERSION
    docker push $REGISTRY/mcp-server:latest
    echo "✅ 镜像推送完成"
fi

echo ""
echo "🎉 构建流程完成!"
echo "镜像标签: mcp-server:$VERSION"

🎯 本节小结

通过这一小节,你已经建立了一个完整的现代化开发工作流:

容器化开发:Docker开发环境,代码热重载
自动化CI/CD:GitHub Actions完整流水线
代码质量保证:Pre-commit钩子,多种检查工具
多环境测试:单元、集成、端到端测试
安全扫描:代码和镜像安全检查
自动化部署:测试和生产环境自动部署

🚀 开发工作流

bash
# 设置开发环境
chmod +x scripts/dev-setup.sh
./scripts/dev-setup.sh

# 开发循环
git checkout -b feature/new-tool
# 编写代码...
git add .
git commit -m "feat: 添加新工具功能"  # 自动触发pre-commit检查

# 运行测试
./scripts/run-tests.sh fast
./scripts/run-tests.sh unit

# 构建和推送
./scripts/build.sh v1.2.0 true

# 创建PR - 自动触发CI流水线
# 合并到main - 自动部署到生产环境

📊 CI/CD优势

  • 快速反馈:每次提交都有完整的测试反馈
  • 质量保证:多层次的代码质量检查
  • 安全保障:自动化安全扫描和检测
  • 零停机部署:蓝绿部署策略
  • 可观测性:完整的部署和运行监控

现在你的MCP项目已经具备了企业级的开发和部署能力!这套工作流可以确保代码质量,加速开发迭代,并提供可靠的部署保障。


👉 继续学习:第5章 高级特性开发