强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

10 - Compose 进阶

10 - Compose 进阶

多环境配置、Profiles、扩展字段、Compose Watch 等高级特性。


10.1 多环境配置策略

方案一:多配置文件覆盖

项目结构:
  compose.yaml          ← 基础配置
  compose.override.yaml ← 开发环境覆盖(自动加载)
  compose.prod.yaml     ← 生产环境覆盖(手动指定)
  compose.test.yaml     ← 测试环境覆盖

compose.yaml — 基础配置:

services:
  app:
    build: ./app
    environment:
      - NODE_ENV=production
      - DB_HOST=db
    depends_on:
      - db

  db:
    image: postgres:16
    volumes:
      - pg-data:/var/lib/postgresql/data

volumes:
  pg-data:

compose.override.yaml — 开发环境(自动加载):

services:
  app:
    build:
      target: development
    ports:
      - "3000:3000"
      - "9229:9229"    # Node.js 调试端口
    volumes:
      - ./app/src:/app/src    # 热重载
    environment:
      - DEBUG=app:*

  db:
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_PASSWORD=devpassword
      - POSTGRES_DB=myapp_dev

compose.prod.yaml — 生产环境:

services:
  app:
    build:
      target: production
    ports:
      - "80:3000"
    restart: unless-stopped
    deploy:
      resources:
        limits:
          cpus: "2.0"
          memory: 1G

  db:
    environment:
      - POSTGRES_PASSWORD_FILE=/run/secrets/db_password
    secrets:
      - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt

使用方式

# 开发环境(自动加载 compose.yaml + compose.override.yaml)
docker compose up -d

# 生产环境
docker compose -f compose.yaml -f compose.prod.yaml up -d

# 或使用简写(注意顺序:基础 → 覆盖)
docker compose -f compose.yaml -f compose.prod.yaml config > final.yaml

方案二:环境变量替换

# compose.yaml
services:
  app:
    image: my-app:${APP_VERSION:-latest}
    ports:
      - "${APP_PORT:-3000}:3000"
    environment:
      - NODE_ENV=${NODE_ENV:-development}
      - LOG_LEVEL=${LOG_LEVEL:-debug}
    deploy:
      resources:
        limits:
          memory: ${MEMORY_LIMIT:-512m}
# .env.development
APP_VERSION=latest
APP_PORT=3000
NODE_ENV=development
LOG_LEVEL=debug
MEMORY_LIMIT=512m

# .env.production
APP_VERSION=1.0.0
APP_PORT=80
NODE_ENV=production
LOG_LEVEL=warn
MEMORY_LIMIT=1G
# 使用环境文件
docker compose --env-file .env.development up -d
docker compose --env-file .env.production up -d

10.2 Profiles(配置文件组)

Profiles 允许按需启动特定服务组,适合开发工具、调试服务等可选组件。

services:
  # 核心服务(始终启动)
  app:
    build: ./app
    ports:
      - "8080:3000"
    profiles: []    # 空 = 始终启动

  db:
    image: postgres:16
    profiles: []

  redis:
    image: redis:7-alpine
    profiles: []

  # 开发工具(仅在 dev profile 下启动)
  adminer:
    image: adminer
    ports:
      - "8081:8080"
    profiles:
      - dev

  mailhog:
    image: mailhog/mailhog
    ports:
      - "1025:1025"
      - "8025:8025"
    profiles:
      - dev
      - test

  # 测试服务
  test-db:
    image: postgres:16
    environment:
      POSTGRES_DB: test
    profiles:
      - test

  # 监控服务
  prometheus:
    image: prom/prometheus
    ports:
      - "9090:9090"
    profiles:
      - monitoring

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    profiles:
      - monitoring
# 仅启动核心服务(无 profile)
docker compose up -d

# 启动核心 + 开发工具
docker compose --profile dev up -d

# 启动核心 + 测试服务
docker compose --profile test up -d

# 启动核心 + 监控
docker compose --profile monitoring up -d

# 启动多个 profile
docker compose --profile dev --profile monitoring up -d

# 通过环境变量启用 profiles
COMPOSE_PROFILES=dev docker compose up -d

10.3 扩展字段(Extension Fields)

使用 YAML 锚点(Anchors)和引用(Aliases)实现配置复用。

基本用法

# 使用 x- 前缀定义扩展字段(Compose 会忽略这些字段)
x-common-env: &common-env
  TZ: Asia/Shanghai
  LANG: C.UTF-8

x-logging: &default-logging
  logging:
    driver: json-file
    options:
      max-size: "10m"
      max-file: "3"

services:
  app:
    image: my-app:latest
    environment:
      <<: *common-env
      APP_ENV: production
    <<: *default-logging

  db:
    image: postgres:16
    environment:
      <<: *common-env
      POSTGRES_PASSWORD: secret
    <<: *default-logging

  redis:
    image: redis:7-alpine
    <<: *default-logging

高级复用模板

x-service-defaults: &service-defaults
  restart: unless-stopped
  logging:
    driver: json-file
    options:
      max-size: "10m"
      max-file: "3"
  networks:
    - app-net

x-healthcheck-defaults: &healthcheck-defaults
  healthcheck:
    interval: 30s
    timeout: 10s
    retries: 3
    start_period: 10s

services:
  web:
    <<: *service-defaults
    image: nginx:alpine
    ports:
      - "80:80"
    <<: *healthcheck-defaults
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:80/"]

  api:
    <<: *service-defaults
    build: ./api
    ports:
      - "8080:3000"
    environment:
      - DB_HOST=db
    depends_on:
      - db
    <<: *healthcheck-defaults
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]

  db:
    <<: *service-defaults
    image: postgres:16
    volumes:
      - pg-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD_FILE=/run/secrets/db_pass
    <<: *healthcheck-defaults
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]

networks:
  app-net:

volumes:
  pg-data:

10.4 Compose Watch(文件监听)

Compose Watch 实时监听文件变化并自动执行操作(开发环境利器)。

services:
  web:
    build: ./web
    develop:
      watch:
        # 文件变化时同步到容器(不重建)
        - action: sync
          path: ./web/src
          target: /app/src
          ignore:
            - "**/node_modules"
            - "**/*.test.js"

        # 依赖文件变化时重建
        - action: rebuild
          path: ./web/package.json

  api:
    build: ./api
    develop:
      watch:
        - action: sync+restart
          path: ./api
          target: /app
          ignore:
            - "**/__pycache__"
            - "**/*.pyc"

Watch 动作类型

动作说明
sync仅同步文件,不重建不重启
rebuild重建镜像并替换容器
sync+restart同步文件并重启容器
# 启动 Watch 模式
docker compose watch

# 在另一个终端修改文件,观察自动同步

10.5 Secrets(密钥管理)

文件式 Secrets(Swarm 模式)

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

  app:
    build: ./app
    secrets:
      - db_password
      - api_key

secrets:
  db_password:
    file: ./secrets/db_password.txt
  api_key:
    file: ./secrets/api_key.txt
# 创建密钥文件
mkdir -p secrets
echo "super-secret-password" > secrets/db_password.txt
echo "my-api-key-12345" > secrets/api_key.txt
chmod 600 secrets/*.txt

# 在容器内读取密钥
docker compose exec app cat /run/secrets/db_password

Secrets vs Environment Variables

特性SecretsEnvironment Variables
存储方式文件挂载于 /run/secrets/进程环境变量
可见性docker inspect 不显示docker inspect 可见
大小限制500KB无明确限制
安全性更高较低
适用场景密码、API Key、证书普通配置变量

10.6 Configs(配置管理)

services:
  nginx:
    image: nginx:alpine
    configs:
      - source: nginx_conf
        target: /etc/nginx/nginx.conf
        mode: 0444

configs:
  nginx_conf:
    file: ./config/nginx.conf

10.7 高级网络配置

services:
  app:
    networks:
      frontend:
        aliases:
          - app.local
          - api.local
        ipv4_address: 172.20.0.100

  db:
    networks:
      backend:
        ipv4_address: 172.21.0.100

networks:
  frontend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24
          gateway: 172.20.0.1
    driver_opts:
      com.docker.network.bridge.name: br-frontend

  backend:
    driver: bridge
    internal: true
    ipam:
      config:
        - subnet: 172.21.0.0/24

  shared-net:
    name: shared-network
    external: true    # 使用已存在的外部网络

10.8 高级卷配置

services:
  app:
    volumes:
      - type: volume
        source: app-data
        target: /app/data
        volume:
          nocopy: true       # 不从容器复制数据

      - type: bind
        source: ./config
        target: /app/config
        read_only: true

      - type: tmpfs
        target: /tmp
        tmpfs:
          size: 100000000    # 100MB

      - type: named_pipe
        source: //./pipe/docker_engine
        target: //./pipe/docker_engine

volumes:
  app-data:
    driver: local
    driver_opts:
      type: nfs
      o: addr=192.168.1.100,rw,nfsvers=4
      device: ":/shared/data"

10.9 Deploy 配置(Swarm 模式)

services:
  web:
    image: nginx:alpine
    deploy:
      replicas: 3
      update_config:
        parallelism: 1          # 每次更新 1 个实例
        delay: 30s              # 更新间隔
        failure_action: rollback
        order: start-first      # 先启动新实例再停止旧的
      rollback_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
      resources:
        limits:
          cpus: "1.0"
          memory: 512M
        reservations:
          cpus: "0.25"
          memory: 128M
      placement:
        constraints:
          - node.role == worker
          - node.labels.zone == east

10.10 实战:完整的多环境项目

project/
├── compose.yaml              # 基础配置
├── compose.override.yaml     # 开发覆盖(自动加载)
├── compose.prod.yaml         # 生产覆盖
├── compose.test.yaml         # 测试覆盖
├── .env                      # 默认环境变量
├── .env.development          # 开发环境变量
├── .env.production           # 生产环境变量
├── config/
│   ├── nginx.conf
│   └── prometheus.yml
├── secrets/                  # .gitignore 排除
│   ├── db_password.txt
│   └── api_key.txt
└── app/
    ├── Dockerfile
    └── src/
# compose.yaml(基础)
x-logging: &default-logging
  logging:
    driver: json-file
    options: { "max-size": "10m", "max-file": "3" }

services:
  app:
    build: ./app
    <<: *default-logging
    depends_on:
      db: { condition: service_healthy }
      redis: { condition: service_started }

  db:
    image: postgres:16-alpine
    <<: *default-logging
    volumes:
      - pg-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
      interval: 10s
      retries: 5

  redis:
    image: redis:7-alpine
    <<: *default-logging
    volumes:
      - redis-data:/data

volumes:
  pg-data:
  redis-data:
# 开发环境
docker compose up -d

# 测试环境
docker compose -f compose.yaml -f compose.test.yaml up -d

# 生产环境
docker compose -f compose.yaml -f compose.prod.yaml up -d

# 验证最终配置
docker compose -f compose.yaml -f compose.prod.yaml config

要点回顾

要点核心内容
多环境基础文件 + 覆盖文件,或环境变量替换
Profiles按需启动服务组,适合开发工具和监控
扩展字段YAML 锚点实现配置复用
Compose Watch文件变化自动同步/重建,开发利器
Secrets文件式密钥管理,比环境变量更安全

注意事项

配置验证: 修改 compose.yaml 后,使用 docker compose config 验证最终配置是否正确。

.env 文件编码: .env 文件必须是 UTF-8 编码,不支持多行值,不支持引号包裹(除非值中包含空格)。

外部网络: 使用 external: true 时,网络必须已存在,否则 docker compose up 会报错。


下一步

11 - Swarm 集群:学习 Docker Swarm 集群管理与服务编排。