Featured image of post 为开发和生产设计可重用的 Docker Compose 配置Featured image of post 为开发和生产设计可重用的 Docker Compose 配置

为开发和生产设计可重用的 Docker Compose 配置

通过链接配置覆盖、管理端口、卷共享和环境文件来维护干燥的撰写文件。

为开发和生产设计可重用的 Docker Compose 配置

Docker Compose 是用于定义和运行多容器应用程序的标准工具。但许多团队陷入了为开发、登台和生产维护单独的 docker-compose.yml 文件的陷阱 - 导致重复、漂移和配置错误。

更好的方法使用组合文件覆盖配置文件环境变量来保持适应每个环境的单一事实来源。


基本 compose.yml 模式

从定义共享服务定义的单个 compose.yml 开始 - 在不同环境中保持不变的映像、命令、端口和环境。

# compose.yml
services:
  app:
    image: myapp:${APP_VERSION:-latest}
    build:
      context: .
      target: ${BUILD_TARGET:-development}
    ports:
      - "${APP_PORT:-3000}:3000"
    environment:
      - NODE_ENV=${NODE_ENV:-development}
      - DATABASE_URL=${DATABASE_URL}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASS}
      POSTGRES_DB: ${DB_NAME}
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  pgdata:

使用具有默认值 (${VAR:-default}) 的环境变量来保持基本文件的通用性。


使用 compose.override.yml 覆盖环境

Docker Compose 会自动读取 compose.override.yml(如果存在)。将此用于仅开发设置 - 切勿提交会影响生产的覆盖。

# compose.override.yml (excluded from production deployments)
services:
  app:
    build:
      target: development
    volumes:
      - .:/app
      - /app/node_modules
    ports:
      - "9229:9229" # debugger
    environment:
      - NODE_ENV=development
      - DEBUG=app:*
    command: npm run dev

  db:
    ports:
      - "5432:5432" # expose for local tools
    volumes:
      - ./scripts/seed:/docker-entrypoint-initdb.d

对于生产,请使用单独的覆盖文件:

# compose.prod.yml
services:
  app:
    build:
      target: production
    restart: always
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 1G
        reservations:
          cpus: '0.5'
          memory: 256M
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

部署方式:docker compose -f compose.yml -f compose.prod.yml up -d


使用环境变体的配置文件

配置文件 (Docker Compose 2.0+) 让您可以根据环境有条件地启用服务。

services:
  mailhog:
    image: mailhog/mailhog
    profiles: ["development", "staging"]
    ports:
      - "8025:8025"

  redis:
    image: redis:7-alpine
    profiles: ["development", "staging", "production"]

  redis-commander:
    image: rediscommander/redis-commander
    profiles: ["development"]
    ports:
      - "8081:8081"

运行 docker compose --profile development up 以仅启动与开发相关的服务。


健康检查和重启策略

始终为支持它们的每项服务定义健康检查。结合重启策略进行自我修复部署。

services:
  app:
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "wget", "--spider", "http://localhost:3000/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 40s

  worker:
    restart: on-failure:5
    depends_on:
      app:
        condition: service_healthy

depends_on.condition: service_healthy 确保工作线程仅在应用程序通过健康检查后启动。


资源限制和扩展

通过设置资源限制来防止失控的容器导致主机崩溃。

services:
  app:
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 128M

  worker:
    deploy:
      mode: replicated
      replicas: 3
      resources:
        limits:
          cpus: '2'
          memory: 1G

注意:deploy 设置适用于 Docker SwarmCompose v3 堆栈。对于普通 docker compose,请使用 --compatibility 标志或特定于平台的限制。


保密管理

切勿在撰写文件中对机密进行硬编码。使用具有受限权限的 Docker 机密或环境文件。

# Using Docker secrets (Swarm mode)
secrets:
  db_password:
    file: ./secrets/db_password.txt

services:
  app:
    secrets:
      - db_password
    environment:
      - DATABASE_URL=postgres://user:${DB_PASSWORD}@db:5432/myapp

对于非 Swarm 设置,请使用 .env 文件:

# .env (never committed to version control)
DB_USER=myapp
DB_PASS=s3cret!
DB_NAME=myapp
APP_PORT=3000

日志记录配置

集中日志记录可防止容器日志垃圾邮件填满您的磁盘。

services:
  app:
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # Production logging to a remote service
  log-collector:
    logging:
      driver: "fluentd"
      options:
        fluentd-address: "localhost:24224"
        tag: "docker.{{.Name}}"

结论

设计可重用的 Docker Compose 配置涉及关注点分离:用于共享定义的 基本 compose.yml、用于特定于环境的设置的 覆盖文件、用于条件服务的 配置文件,以及用于机密和配置的 环境变量

这种分层方法消除了重复,减少了配置偏差,并使您的部署管道在开发、登台和生产过程中可预测。采用这些模式可以充满信心地发货。