Skip to content

Compose 文件详解

docker-compose.yml 使用 YAML 格式,本节介绍所有常用配置项的详细说明。

文件结构

yaml
# Compose 文件版本(v2 已不需要指定 version)
# version: "3.9"  # 可省略

services:        # 服务定义
  service-name:
    ...

networks:        # 网络定义
  network-name:
    ...

volumes:         # 数据卷定义
  volume-name:
    ...

configs:         # 配置文件(Swarm 模式)
  config-name:
    ...

secrets:         # 密钥(Swarm 模式)
  secret-name:
    ...

services 服务配置

image — 使用现有镜像

yaml
services:
  web:
    image: nginx:alpine
  db:
    image: mysql:8.0
  cache:
    image: redis:7-alpine

build — 构建镜像

yaml
services:
  api:
    # 简写:使用当前目录的 Dockerfile
    build: .

    # 完整写法
    build:
      context: ./api          # 构建上下文
      dockerfile: Dockerfile  # Dockerfile 文件名
      args:                   # 构建参数
        NODE_ENV: production
        VERSION: 1.0.0
      target: production      # 多阶段构建的目标阶段
      cache_from:             # 缓存来源
        - myapp:latest
      labels:
        version: "1.0"

ports — 端口映射

yaml
services:
  web:
    ports:
      - "80:80"           # 宿主机:容器
      - "443:443"
      - "8080"            # 随机宿主机端口
      - "127.0.0.1:8080:80"  # 绑定到指定 IP
    
    # 完整写法
    ports:
      - target: 80
        published: 8080
        protocol: tcp
        mode: host

environment — 环境变量

yaml
services:
  api:
    environment:
      # 键值对
      NODE_ENV: production
      PORT: 3000
      # 引用 .env 文件或 shell 环境变量
      DB_PASSWORD: ${DB_PASSWORD}
      # 只写 key,从 shell 环境变量获取值
      SECRET_KEY:

    # 或者使用列表格式
    environment:
      - NODE_ENV=production
      - PORT=3000

env_file — 从文件加载环境变量

yaml
services:
  api:
    env_file:
      - .env           # 默认 .env 文件
      - .env.local     # 覆盖配置
      - ./api/.env     # 指定路径

volumes — 挂载配置

yaml
services:
  mysql:
    volumes:
      # 命名卷
      - mysql-data:/var/lib/mysql
      
      # 绑定挂载
      - ./config/my.cnf:/etc/mysql/conf.d/custom.cnf:ro
      - ./logs:/var/log/mysql
      
      # 匿名卷
      - /tmp/cache
      
      # 完整写法
      - type: volume
        source: mysql-data
        target: /var/lib/mysql
      - type: bind
        source: ./config
        target: /etc/app/config
        read_only: true

volumes:
  mysql-data:   # 声明命名卷

networks — 网络配置

yaml
services:
  api:
    networks:
      - backend
      - frontend
      
  # 完整写法(指定 IP、别名)
  db:
    networks:
      backend:
        ipv4_address: 172.20.0.10
        aliases:
          - database

networks:
  backend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24
  frontend:
    driver: bridge

depends_on — 服务依赖

yaml
services:
  api:
    depends_on:
      - db      # 简写:db 启动后启动 api(不等待健康)
    
    # 等待健康状态
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started  # 仅等待启动

  db:
    image: mysql:8.0
    healthcheck:
      test: ["CMD", "mysqladmin", "ping"]
      interval: 10s
      retries: 5

restart — 重启策略

yaml
services:
  api:
    restart: unless-stopped  # 推荐生产使用

  # 可选值:no / always / on-failure / unless-stopped
  worker:
    restart: on-failure:3   # 失败后最多重启 3 次

command — 覆盖默认命令

yaml
services:
  api:
    image: node:20-alpine
    command: node app.js           # shell 格式
    command: ["node", "app.js"]   # exec 格式(推荐)
    
  worker:
    image: myapp
    command: ["python", "worker.py", "--queue", "high"]

entrypoint — 覆盖入口点

yaml
services:
  app:
    entrypoint: /entrypoint.sh
    entrypoint: ["sh", "/entrypoint.sh"]

healthcheck — 健康检查

yaml
services:
  api:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    
  # 禁用健康检查
  worker:
    healthcheck:
      disable: true

deploy — 部署配置(Swarm 模式)

yaml
services:
  api:
    deploy:
      replicas: 3           # 实例数
      resources:
        limits:
          cpus: "0.5"
          memory: 512M
        reservations:
          cpus: "0.25"
          memory: 256M
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
      update_config:
        parallelism: 1      # 每次更新 1 个实例
        delay: 10s          # 每次更新间隔
        failure_action: rollback

logging — 日志配置

yaml
services:
  api:
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
    
  # 输出到 syslog
  worker:
    logging:
      driver: syslog
      options:
        syslog-address: "udp://loghost:514"

labels — 标签

yaml
services:
  api:
    labels:
      - "app=myapp"
      - "env=production"
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.example.com`)"

profiles — 服务配置集

yaml
services:
  api:
    image: myapi  # 总是启动

  debug-tools:
    image: alpine
    profiles:
      - debug     # 只在 debug 配置集下启动
    command: sh

  migrate:
    image: myapp
    profiles:
      - tools     # 工具类服务
    command: migrate
bash
# 启动特定 profile
docker compose --profile debug up -d
docker compose --profile tools run migrate

完整示例

yaml
services:
  # PostgreSQL 数据库
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER:-myuser}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB:-mydb}
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-myuser}"]
      interval: 10s
      timeout: 5s
      retries: 5
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  # Redis 缓存
  redis:
    image: redis:7-alpine
    restart: unless-stopped
    command: redis-server --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis-data:/data
    networks:
      - backend
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3

  # 后端 API
  api:
    build:
      context: .
      dockerfile: Dockerfile
      target: production
    restart: unless-stopped
    environment:
      NODE_ENV: production
      DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
      REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379
    ports:
      - "3000:3000"
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - backend
      - frontend
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"

  # Nginx 反向代理
  nginx:
    image: nginx:alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      api:
        condition: service_healthy
    networks:
      - frontend

volumes:
  postgres-data:
    labels:
      backup: daily
  redis-data:

networks:
  backend:
    driver: bridge
  frontend:
    driver: bridge

总结

Compose 文件最常用的配置项:

配置项作用
image / build指定镜像或构建方式
ports端口映射
environment环境变量
volumes数据挂载
networks网络连接
depends_on服务依赖
restart重启策略
healthcheck健康检查
logging日志配置
deploy部署配置(Swarm)