⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议
Skip to content

10.3.1 编排文件怎么写——Compose 文件结构:服务定义与依赖关系

一个 YAML 文件,定义整个应用栈。

文件结构概览

yaml
# docker-compose.yml 基本结构
services:     # 服务定义(必需)
  web:
    ...
  api:
    ...

volumes:      # 数据卷定义(可选)
  db-data:

networks:     # 网络定义(可选)
  app-network:

完整示例:全栈应用

yaml
services:
  # Next.js 前端
  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
    environment:
      - NEXT_PUBLIC_API_URL=http://api:3001
    depends_on:
      - api

  # NestJS 后端
  api:
    build: ./api
    ports:
      - "3001:3001"
    environment:
      - DATABASE_URL=postgresql://postgres:password@postgres:5432/mydb
      - REDIS_URL=redis://redis:6379
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_started

  # PostgreSQL 数据库
  postgres:
    image: postgres:15
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=mydb
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Redis 缓存
  redis:
    image: redis:7-alpine
    volumes:
      - redis-data:/data

volumes:
  postgres-data:
  redis-data:

服务配置详解

镜像来源

yaml
services:
  # 方式一:使用现有镜像
  postgres:
    image: postgres:15

  # 方式二:从 Dockerfile 构建
  api:
    build: ./api
    # 或详细配置
    build:
      context: ./api
      dockerfile: Dockerfile.prod
      args:
        - NODE_ENV=production

端口映射

yaml
services:
  api:
    ports:
      - "3001:3001"           # 宿主机:容器
      - "127.0.0.1:3001:3001" # 仅本机访问
    expose:
      - "3001"                # 仅容器间访问,不对外

环境变量

yaml
services:
  api:
    # 方式一:直接定义
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://...
    
    # 方式二:从文件加载
    env_file:
      - .env
      - .env.production

数据卷

yaml
services:
  postgres:
    volumes:
      # 命名卷(推荐,Docker 管理)
      - postgres-data:/var/lib/postgresql/data
      # 绑定挂载(直接映射主机目录)
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro

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

依赖关系配置

基本依赖

yaml
services:
  api:
    depends_on:
      - postgres
      - redis

问题:depends_on 只保证启动顺序,不保证服务就绪。

带健康检查的依赖

yaml
services:
  api:
    depends_on:
      postgres:
        condition: service_healthy  # 等待健康检查通过
      redis:
        condition: service_started  # 只等待启动

重启策略

yaml
services:
  api:
    restart: always  # 总是重启

# 可选值
# no          - 不重启(默认)
# always      - 总是重启
# on-failure  - 仅失败时重启
# unless-stopped - 除非手动停止

资源限制

yaml
services:
  api:
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 512M
        reservations:
          cpus: '0.5'
          memory: 256M

文件组织最佳实践

project/
├── docker-compose.yml          # 基础配置
├── docker-compose.override.yml # 开发环境覆盖(自动加载)
├── docker-compose.prod.yml     # 生产环境配置
├── .env                        # 环境变量
├── frontend/
│   └── Dockerfile
└── api/
    └── Dockerfile

常见错误

错误原因解决方案
service "api" depends on undefined service依赖的服务名拼写错误检查服务名
port is already allocated端口被占用修改端口或停止占用进程
volume "xxx" not found卷未声明在 volumes 顶级键中声明

AI 协作指南

向 AI 描述需求时:

请帮我生成一个 docker-compose.yml,包含:
- Next.js 前端(端口 3000)
- NestJS 后端(端口 3001)
- PostgreSQL 数据库
- Redis 缓存
要求:后端等待数据库健康后再启动,数据需要持久化

关键术语:services、depends_on、healthcheck、volumes、networks