Skip to content

03_docker_compose

yaml
# ============================================================
#                Docker Compose 配置详解
# ============================================================
# Docker Compose 用于定义和运行多容器 Docker 应用
# 配置文件默认名:docker-compose.yml 或 compose.yaml
#
# 常用命令:
#   docker compose up -d          # 启动所有服务
#   docker compose down           # 停止并删除容器
#   docker compose ps             # 查看服务状态
#   docker compose logs -f        # 查看日志
#   docker compose exec web bash  # 进入容器
# ============================================================

# Compose 文件版本(可选,新版本不需要)
# version: "3.8"

# ============================================================
#                    服务定义
# ============================================================
services:

  # ----------------------------------------------------------
  #                    Web 应用服务
  # ----------------------------------------------------------
  web:
    # 镜像名称(二选一:image 或 build)
    image: nginx:alpine

    # 或者从 Dockerfile 构建
    # build:
    #   context: .                    # 构建上下文路径
    #   dockerfile: Dockerfile        # Dockerfile 文件名
    #   args:                         # 构建参数
    #     - NODE_ENV=production
    #   target: production            # 多阶段构建目标

    # 容器名称
    container_name: my-web

    # 端口映射
    ports:
      - "80:80"                       # 宿主机:容器
      - "443:443"
      - "127.0.0.1:8080:80"          # 只绑定本地

    # 数据卷挂载
    volumes:
      - ./nginx/html:/usr/share/nginx/html          # 绑定挂载
      - ./nginx/conf.d:/etc/nginx/conf.d:ro         # 只读挂载
      - nginx_logs:/var/log/nginx                    # 命名卷

    # 环境变量
    environment:
      - TZ=Asia/Shanghai
      - NGINX_HOST=localhost

    # 或从文件读取环境变量
    # env_file:
    #   - .env
    #   - .env.local

    # 网络
    networks:
      - frontend
      - backend

    # 依赖关系(决定启动顺序)
    depends_on:
      - api
      - db

    # 更严格的依赖(等待服务健康)
    # depends_on:
    #   db:
    #     condition: service_healthy
    #   redis:
    #     condition: service_started

    # 重启策略
    restart: unless-stopped
    # 可选值:no, always, on-failure, unless-stopped

    # 健康检查
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

    # 资源限制
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M

    # 日志配置
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"


  # ----------------------------------------------------------
  #                    API 服务
  # ----------------------------------------------------------
  api:
    build:
      context: ./api
      dockerfile: Dockerfile
      args:
        NODE_ENV: production

    container_name: my-api

    ports:
      - "3000:3000"

    volumes:
      - ./api:/app
      - /app/node_modules              # 排除 node_modules

    environment:
      NODE_ENV: production
      PORT: 3000
      DB_HOST: db
      DB_PORT: 5432
      DB_NAME: ${DB_NAME:-myapp}       # 使用环境变量,默认值 myapp
      DB_USER: ${DB_USER}
      DB_PASSWORD: ${DB_PASSWORD}
      REDIS_HOST: redis
      REDIS_PORT: 6379

    env_file:
      - .env

    networks:
      - backend

    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started

    restart: unless-stopped

    # 运行命令覆盖
    command: ["npm", "run", "start:prod"]

    # 或使用 entrypoint
    # entrypoint: ["/docker-entrypoint.sh"]

    # 工作目录
    working_dir: /app

    # 用户
    user: "node"

    # 额外的 hosts 映射
    extra_hosts:
      - "host.docker.internal:host-gateway"


  # ----------------------------------------------------------
  #                    数据库服务
  # ----------------------------------------------------------
  db:
    image: postgres:15-alpine

    container_name: my-db

    ports:
      - "5432:5432"

    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init-scripts:/docker-entrypoint-initdb.d    # 初始化脚本

    environment:
      POSTGRES_DB: ${DB_NAME:-myapp}
      POSTGRES_USER: ${DB_USER:-postgres}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      PGDATA: /var/lib/postgresql/data/pgdata

    networks:
      - backend

    restart: unless-stopped

    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-postgres}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

    # 共享内存大小(PostgreSQL 需要)
    shm_size: 256mb


  # ----------------------------------------------------------
  #                    Redis 缓存服务
  # ----------------------------------------------------------
  redis:
    image: redis:7-alpine

    container_name: my-redis

    ports:
      - "6379:6379"

    volumes:
      - redis_data:/data
      - ./redis/redis.conf:/usr/local/etc/redis/redis.conf

    # 自定义启动命令
    command: redis-server /usr/local/etc/redis/redis.conf --appendonly yes

    networks:
      - backend

    restart: unless-stopped

    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5


  # ----------------------------------------------------------
  #                    MySQL 数据库
  # ----------------------------------------------------------
  mysql:
    image: mysql:8.0

    container_name: my-mysql

    ports:
      - "3306:3306"

    volumes:
      - mysql_data:/var/lib/mysql
      - ./mysql/conf.d:/etc/mysql/conf.d
      - ./mysql/init:/docker-entrypoint-initdb.d

    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE:-myapp}
      MYSQL_USER: ${MYSQL_USER:-user}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      TZ: Asia/Shanghai

    networks:
      - backend

    restart: unless-stopped

    command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5


  # ----------------------------------------------------------
  #                    MongoDB 数据库
  # ----------------------------------------------------------
  mongo:
    image: mongo:6

    container_name: my-mongo

    ports:
      - "27017:27017"

    volumes:
      - mongo_data:/data/db
      - ./mongo/init:/docker-entrypoint-initdb.d

    environment:
      MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER:-root}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD}
      MONGO_INITDB_DATABASE: ${MONGO_DATABASE:-myapp}

    networks:
      - backend

    restart: unless-stopped


  # ----------------------------------------------------------
  #                    Elasticsearch
  # ----------------------------------------------------------
  elasticsearch:
    image: elasticsearch:8.10.0

    container_name: my-elasticsearch

    ports:
      - "9200:9200"
      - "9300:9300"

    volumes:
      - es_data:/usr/share/elasticsearch/data

    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"

    networks:
      - backend

    restart: unless-stopped

    deploy:
      resources:
        limits:
          memory: 1G


  # ----------------------------------------------------------
  #                    RabbitMQ 消息队列
  # ----------------------------------------------------------
  rabbitmq:
    image: rabbitmq:3-management-alpine

    container_name: my-rabbitmq

    ports:
      - "5672:5672"     # AMQP
      - "15672:15672"   # 管理界面

    volumes:
      - rabbitmq_data:/var/lib/rabbitmq

    environment:
      RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER:-admin}
      RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD}

    networks:
      - backend

    restart: unless-stopped


  # ----------------------------------------------------------
  #                    MinIO 对象存储
  # ----------------------------------------------------------
  minio:
    image: minio/minio:latest

    container_name: my-minio

    ports:
      - "9000:9000"     # API
      - "9001:9001"     # 控制台

    volumes:
      - minio_data:/data

    environment:
      MINIO_ROOT_USER: ${MINIO_USER:-admin}
      MINIO_ROOT_PASSWORD: ${MINIO_PASSWORD}

    command: server /data --console-address ":9001"

    networks:
      - backend

    restart: unless-stopped


# ============================================================
#                    网络定义
# ============================================================
networks:
  # 前端网络
  frontend:
    driver: bridge

  # 后端网络
  backend:
    driver: bridge
    # 自定义网络配置
    # ipam:
    #   config:
    #     - subnet: 172.20.0.0/16

  # 使用外部已存在的网络
  # external_network:
  #   external: true


# ============================================================
#                    数据卷定义
# ============================================================
volumes:
  # 命名卷(由 Docker 管理)
  nginx_logs:
  postgres_data:
  redis_data:
  mysql_data:
  mongo_data:
  es_data:
  rabbitmq_data:
  minio_data:

  # 带选项的卷
  # custom_volume:
  #   driver: local
  #   driver_opts:
  #     type: nfs
  #     o: addr=192.168.1.100,rw
  #     device: ":/path/to/dir"


# ============================================================
#                    配置定义(Configs)
# ============================================================
# configs:
#   nginx_config:
#     file: ./nginx/nginx.conf
#
#   # 使用配置
#   # services:
#   #   web:
#   #     configs:
#   #       - source: nginx_config
#   #         target: /etc/nginx/nginx.conf


# ============================================================
#                    密钥定义(Secrets)
# ============================================================
# secrets:
#   db_password:
#     file: ./secrets/db_password.txt
#
#   # 使用密钥
#   # services:
#   #   db:
#   #     secrets:
#   #       - db_password
#     # 密钥会挂载到 /run/secrets/db_password

💬 讨论

使用 GitHub 账号登录后即可参与讨论

基于 MIT 许可发布