mcpField
D
docker-compose-orchestration

docker-compose-orchestration

github.com/manutej云与 DevOps623.0k 次安装40 周前更新
代码仓库

关于 docker-compose-orchestration

这是一个介绍如何使用 Docker Compose 配置和运行多容器应用的技能,面向管理应用服务栈的开发者。内容涵盖服务定义、网络、存储、健康检查、生命周期命令,以及开发和部署配置。

主要功能

  1. 01用 YAML 定义多服务应用栈
  2. 02配置服务依赖和网络
  3. 03管理持久化及共享卷
  4. 04设置服务健康检查
  5. 05运行、重建和扩展 Compose 项目
  6. 06使用不同环境的 Compose 文件

适用场景

  1. 01共同运行前端、后端和数据库服务
  2. 02创建可复现的本地开发环境
  3. 03在工作站上测试分布式系统
  4. 04准备预发布或生产环境配置

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/manutej/luxor-claude-marketplace --skill docker-compose-orchestration

安装后在 Claude Code 中输入/docker-compose-orchestration确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

.skill-info.txt
EXAMPLES.md
README.md

详细介绍

Docker Compose 编排

用于使用 Docker Compose 编排多容器应用的综合技能。此技能支持通过服务定义、网络策略、卷管理、健康检查和适用于生产环境的配置,快速开发、部署和管理容器化应用。

使用此技能的时机

适用于以下场景:

  • 构建多容器应用(微服务、全栈应用)
  • 设置包含数据库、缓存和服务的开发环境
  • 将前端、后端和数据库服务编排在一起
  • 管理服务依赖关系和启动顺序
  • 配置网络和服务间通信
  • 使用卷实现持久化存储
  • 将应用部署到开发、预发布或生产环境
  • 创建可复现的开发环境
  • 管理应用生命周期(启动、停止、重建、扩缩容)
  • 监控应用健康状况并实现健康检查
  • 从单容器迁移到多服务架构
  • 在本地测试分布式系统

核心概念

Docker Compose 理念

Docker Compose 通过以下方式简化多容器应用管理:

  • 声明式配置:在 YAML 中定义完整的应用栈
  • 服务抽象:每个组件都是一个拥有独立配置的服务
  • 自动网络:服务可以通过名称自动相互通信
  • 卷管理:在容器间持久化数据并共享存储
  • 环境隔离:每个项目都有自己的网络命名空间
  • 可复现性:同一配置可在所有环境中使用
Docker Compose 核心实体
  1. 服务:各个容器及其配置
  2. 网络:服务之间的通信通道
  3. 卷:持久化存储和数据共享
  4. 配置:非敏感配置文件
  5. 密钥:敏感数据(密码、API 密钥)
  6. 项目:单一命名空间下的一组服务
Compose 文件结构
version: "3.8"  # Compose file format version

services:       # Define containers
  service-name:
    # Service configuration

networks:       # Define custom networks
  network-name:
    # Network configuration

volumes:        # Define named volumes
  volume-name:
    # Volume configuration

configs:        # Application configs (optional)
  config-name:
    # Config source

secrets:        # Sensitive data (optional)
  secret-name:
    # Secret source

服务定义模式

基本服务定义
services:
  web:
    image: nginx:alpine           # Use existing image
    container_name: my-web        # Custom container name
    restart: unless-stopped       # Restart policy
    ports:
      - "80:80"                   # Host:Container port mapping
    environment:
      - ENV_VAR=value             # Environment variables
    volumes:
      - ./html:/usr/share/nginx/html  # Volume mount
    networks:
      - frontend                  # Connect to network
基于构建的服务
services:
  app:
    build:
      context: ./app              # Build context directory
      dockerfile: Dockerfile      # Custom Dockerfile
      args:                       # Build arguments
        NODE_ENV: development
      target: development         # Multi-stage build target
    image: myapp:latest           # Tag resulting image
    ports:
      - "3000:3000"
带依赖项的服务
services:
  web:
    image: nginx
    depends_on:
      db:
        condition: service_healthy  # Wait for health check
      redis:
        condition: service_started  # Wait for start only

  db:
    image: postgres:15
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

  redis:
    image: redis:alpine
带高级配置的服务
services:
  backend:
    build: ./backend
    command: npm run dev          # Override default command
    working_dir: /app             # Set working directory
    user: "1000:1000"             # Run as specific user
    hostname: api-server          # Custom hostname
    domainname: example.com       # Domain name
    env_file:
      - .env                      # Load env from file
      - .env.local
    environment:
      DATABASE_URL: "postgresql://db:5432/myapp"
      REDIS_URL: "redis://cache:6379"
    volumes:
      - ./backend:/app            # Source code mount
      - /app/node_modules         # Preserve node_modules
      - app-data:/data            # Named volume
    ports:
      - "3000:3000"               # Application port
      - "9229:9229"               # Debug port
    expose:
      - "8080"                    # Expose to other services only
    networks:
      - backend
      - frontend
    labels:
      - "com.example.description=Backend API"
      - "com.example.version=1.0"
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 1G
        reservations:
          cpus: '0.5'
          memory: 512M

多容器应用模式

模式 1:全栈 Web 应用

场景: React 前端 + Node.js 后端 + PostgreSQL 数据库

version: "3.8"

services:
  # Frontend React Application
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
      target: development
    ports:
      - "3000:3000"
    volumes:
      - ./frontend/src:/app/src
      - /app/node_modules
    environment:
      - REACT_APP_API_URL=http://localhost:4000/api
      - CHOKIDAR_USEPOLLING=true  # For hot reload
    networks:
      - frontend
    depends_on:
      - backend

  # Backend Node.js API
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "4000:4000"
      - "9229:9229"  # Debugger
    volumes:
      - ./backend:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - DATABASE_URL=postgresql://postgres:password@db:5432/myapp
      - REDIS_URL=redis://cache:6379
      - JWT_SECRET=dev-secret
    env_file:
      - ./backend/.env.local
    networks:
      - frontend
      - backend
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started
    command: npm run dev

  # PostgreSQL Database
  db:
    image: postgres:15-alpine
    container_name: postgres-db
    restart: unless-stopped
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=myapp
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Redis Cache
  cache:
    image: redis:7-alpine
    container_name: redis-cache
    restart: unless-stopped
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    networks:
      - backend
    command: redis-server --appendonly yes
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5

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

volumes:
  postgres-data:
    driver: local
  redis-data:
    driver: local
模式 2:微服务架构

场景: 包含反向代理和服务发现的多个服务

version: "3.8"

services:
  # NGINX Reverse Proxy
  proxy:
    image: nginx:alpine
    container_name: reverse-proxy
    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
    networks:
      - public
    depends_on:
      - auth-service
      - user-service
      - order-service
    restart: unless-stopped

  # Authentication Service
  auth-service:
    build: ./services/auth
    container_name: auth-service
    expose:
      - "8001"
    environment:
      - SERVICE_NAME=auth
      - DATABASE_URL=postgresql://db:5432/auth_db
      - JWT_SECRET=${JWT_SECRET}
    networks:
      - public
      - internal
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8001/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  # User Service
  user-service:
    build: ./services/user
    container_name: user-service
    expose:
      - "8002"
    environment:
      - SERVICE_NAME=user
      - DATABASE_URL=postgresql://db:5432/user_db
      - AUTH_SERVICE_URL=http://auth-service:8001
    networks:
      - public
      - internal
    depends_on:
      - auth-service
      - db
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8002/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  # Order Service
  order-service:
    build: ./services/order
    container_name: order-service
    expose:
      - "8003"
    environment:
      - SERVICE_NAME=order
      - DATABASE_URL=postgresql://db:5432/order_db
      - USER_SERVICE_URL=http://user-service:8002
      - RABBITMQ_URL=amqp://rabbitmq:5672
    networks:
      - public
      - internal
    depends_on:
      - user-service
      - db
      - rabbitmq
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8003/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  # Shared PostgreSQL Database
  db:
    image: postgres:15-alpine
    container_name: postgres-db
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./database/init-multi-db.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - internal
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

  # RabbitMQ Message Broker
  rabbitmq:
    image: rabbitmq:3-management-alpine
    container_name: rabbitmq
    ports:
      - "5672:5672"   # AMQP
      - "15672:15672" # Management UI
    environment:
      - RABBITMQ_DEFAULT_USER=admin
      - RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD}
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq
    networks:
      - internal
    healthcheck:
      test: ["CMD", "rabbitmq-diagnostics", "ping"]
      interval: 30s
      timeout: 10s
      retries: 5

networks:
  public:
    driver: bridge
  internal:
    driver: bridge
    internal: true  # No external access

volumes:
  postgres-data:
  rabbitmq-data:
模式 3:支持热重载的开发环境

场景: 支持代码实时重载和调试的开发环境

version: "3.8"

services:
  # Development Frontend
  frontend-dev:
    build:
      context: ./frontend
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
      - "9222:9222"  # Chrome DevTools
    volumes:
      - ./frontend:/app
      - /app/node_modules
      - /app/.next  # Next.js build cache
    environment:
      - NODE_ENV=development
      - WATCHPACK_POLLING=true
      - NEXT_PUBLIC_API_URL=http://localhost:4000
    networks:
      - dev-network
    stdin_open: true
    tty: true
    command: npm run dev

  # Development Backend
  backend-dev:
    build:
      context: ./backend
      dockerfile: Dockerfile.dev
    ports:
      - "4000:4000"
      - "9229:9229"  # Node.js debugger
    volumes:
      - ./backend:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - DEBUG=app:*
      - DATABASE_URL=postgresql://postgres:dev@db:5432/dev_db
    networks:
      - dev-network
    depends_on:
      - db
      - mailhog
    command: npm run dev:debug

  # PostgreSQL with pgAdmin
  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_PASSWORD=dev
      - POSTGRES_DB=dev_db
    ports:
      - "5432:5432"
    volumes:
      - dev-db-data:/var/lib/postgresql/data
    networks:
      - dev-network

  pgadmin:
    image: dpage/pgadmin4:latest
    environment:
      - [email protected]
      - PGADMIN_DEFAULT_PASSWORD=admin
    ports:
      - "5050:80"
    networks:
      - dev-network
    depends_on:
      - db

  # MailHog for Email Testing
  mailhog:
    image: mailhog/mailhog:latest
    ports:
      - "1025:1025"  # SMTP
      - "8025:8025"  # Web UI
    networks:
      - dev-network

networks:
  dev-network:
    driver: bridge

volumes:
  dev-db-data:

网络策略

默认桥接网络
services:
  web:
    image: nginx
    # Automatically connected to default network

  app:
    image: myapp
    # Can communicate with 'web' via service name
自定义桥接网络
version: "3.8"

services:
  frontend:
    image: react-app
    networks:
      - public

  backend:
    image: api-server
    networks:
      - public    # Accessible from frontend
      - private   # Accessible from database

  database:
    image: postgres
    networks:
      - private   # Isolated from frontend

networks:
  public:
    driver: bridge
  private:
    driver: bridge
    internal: true  # No internet access
网络别名
services:
  api:
    image: api-server
    networks:
      backend:
        aliases:
          - api-server
          - api.internal
          - api-v1.internal

networks:
  backend:
    driver: bridge
主机网络模式
services:
  app:
    image: myapp
    network_mode: "host"  # Use host network stack
    # No port mapping needed, uses host ports directly
自定义网络配置
networks:
  custom-network:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: br-custom
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16
          gateway: 172.28.0.1
    labels:
      - "com.example.description=Custom network"

卷管理

命名卷
version: "3.8"

services:
  db:
    image: postgres:15
    volumes:
      - postgres-data:/var/lib/postgresql/data  # Named volume

  backup:
    image: postgres:15
    volumes:
      - postgres-data:/backup:ro  # Read-only mount
    command: pg_dump -U postgres > /backup/dump.sql

volumes:
  postgres-data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /path/on/host
绑定挂载
services:
  web:
    image: nginx
    volumes:
      # Relative path bind mount
      - ./html:/usr/share/nginx/html

      # Absolute path bind mount
      - /var/log/nginx:/var/log/nginx

      # Read-only bind mount
      - ./config/nginx.conf:/etc/nginx/nginx.conf:ro
tmpfs 挂载(内存中)
services:
  app:
    image: myapp
    tmpfs:
      - /tmp
      - /run
    # Or with options:
    volumes:
      - type: tmpfs
        target: /app/cache
        tmpfs:
          size: 1000000000  # 1GB
服务间共享卷
services:
  app:
    image: myapp
    volumes:
      - shared-data:/data

  worker:
    image: worker
    volumes:
      - shared-data:/data

  backup:
    image: backup-tool
    volumes:
      - shared-data:/backup:ro

volumes:
  shared-data:
高级卷配置
volumes:
  data:
    driver: local
    driver_opts:
      type: "nfs"
      o: "addr=10.40.0.199,nolock,soft,rw"
      device: ":/docker/example"

  cache:
    driver: local
    driver_opts:
      type: tmpfs
      device: tmpfs
      o: "size=100m,uid=1000"

  external-volume:
    external: true  # Volume created outside Compose
    name: my-existing-volume

健康检查

HTTP 健康检查
services:
  web:
    image: nginx
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
数据库健康检查
services:
  postgres:
    image: postgres:15
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

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

  mongodb:
    image: mongo:6
    healthcheck:
      test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
      interval: 10s
      timeout: 5s
      retries: 5
应用健康检查
services:
  app:
    build: ./app
    healthcheck:
      test: ["CMD", "node", "healthcheck.js"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

  api:
    build: ./api
    healthcheck:
      test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
复杂健康检查
services:
  redis:
    image: redis:alpine
    healthcheck:
      test: |
        sh -c '
        redis-cli ping | grep PONG &&
        redis-cli --raw incr ping | grep 1
        '
      interval: 10s
      timeout: 3s
      retries: 5

开发与生产配置

基础配置(compose.yaml)
version: "3.8"

services:
  web:
    image: myapp:latest
    environment:
      - NODE_ENV=production
    networks:
      - app-network

  db:
    image: postgres:15-alpine
    networks:
      - app-network

networks:
  app-network:
    driver: bridge
开发覆盖配置(compose.override.yaml)
# Automatically merged with compose.yaml in development
version: "3.8"

services:
  web:
    build:
      context: .
      target: development
    volumes:
      - ./src:/app/src  # Live code reload
      - /app/node_modules
    ports:
      - "3000:3000"     # Expose for local access
      - "9229:9229"     # Debugger port
    environment:
      - NODE_ENV=development
      - DEBUG=*
    command: npm run dev

  db:
    ports:
      - "5432:5432"     # Expose for local tools
    environment:
      - POSTGRES_PASSWORD=dev
    volumes:
      - ./init-dev.sql:/docker-entrypoint-initdb.d/init.sql
生产配置(compose.prod.yaml)
version: "3.8"

services:
  web:
    image: myapp:${VERSION:-latest}
    restart: always
    environment:
      - NODE_ENV=production
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '2'
          memory: 2G
        reservations:
          cpus: '1'
          memory: 1G
      update_config:
        parallelism: 1
        delay: 10s
        failure_action: rollback
      rollback_config:
        parallelism: 1
        delay: 5s
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"

  db:
    image: postgres:15-alpine
    restart: always
    environment:
      - POSTGRES_PASSWORD_FILE=/run/secrets/db_password
    secrets:
      - db_password
    volumes:
      - postgres-data:/var/lib/postgresql/data
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 4G

  # Production additions
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/prod.conf:/etc/nginx/nginx.conf:ro
      - ssl-certs:/etc/nginx/ssl:ro
    restart: always
    depends_on:
      - web

secrets:
  db_password:
    external: true

volumes:
  postgres-data:
    driver: local
  ssl-certs:
    external: true
预发布配置(compose.staging.yaml)
version: "3.8"

services:
  web:
    image: myapp:staging-${VERSION:-latest}
    restart: unless-stopped
    environment:
      - NODE_ENV=staging
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: '1'
          memory: 1G

  db:
    environment:
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    volumes:
      - staging-db-data:/var/lib/postgresql/data

volumes:
  staging-db-data:

Docker Compose 必备命令

项目管理
# Start services
docker compose up                    # Foreground
docker compose up -d                 # Detached (background)
docker compose up --build            # Rebuild images
docker compose up --force-recreate   # Recreate containers
docker compose up --scale web=3      # Scale service to 3 instances

# Stop services
docker compose stop                  # Stop containers
docker compose down                  # Stop and remove containers/networks
docker compose down -v               # Also remove volumes
docker compose down --rmi all        # Also remove images

# Restart services
docker compose restart               # Restart all services
docker compose restart web           # Restart specific service
服务管理
# Build services
docker compose build                 # Build all services
docker compose build web             # Build specific service
docker compose build --no-cache      # Build without cache
docker compose build --pull          # Pull latest base images

# View services
docker compose ps                    # List containers
docker compose ps -a                 # Include stopped containers
docker compose top                   # Display running processes
docker compose images                # List images

# Logs
docker compose logs                  # View all logs
docker compose logs -f               # Follow logs
docker compose logs web              # Service-specific logs
docker compose logs --tail=100 web   # Last 100 lines
执行与调试
# Execute commands
docker compose exec web sh           # Interactive shell
docker compose exec web npm test     # Run command
docker compose exec -u root web sh   # Run as root

# Run one-off commands
docker compose run web npm install   # Run command in new container
docker compose run --rm web test     # Remove container after
docker compose run --no-deps web sh  # Don't start dependencies
配置管理
# Multiple compose files
docker compose -f compose.yaml -f compose.prod.yaml up

# Environment-specific deployment
docker compose --env-file .env.prod up
docker compose -p myproject up       # Custom project name

# Configuration validation
docker compose config                # Validate and view config
docker compose config --quiet        # Only validation
docker compose config --services     # List services
docker compose config --volumes      # List volumes

15+ 个 Compose 示例

示例 1:NGINX + PHP + MySQL(LAMP 技术栈)
version: "3.8"

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./public:/var/www/html
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
    networks:
      - lamp
    depends_on:
      - php

  php:
    build:
      context: ./php
      dockerfile: Dockerfile
    volumes:
      - ./public:/var/www/html
    networks:
      - lamp
    depends_on:
      - mysql

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: myapp
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - lamp

networks:
  lamp:

volumes:
  mysql-data:
示例 2:Django + PostgreSQL + Redis + Celery
version: "3.8"

services:
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://postgres:postgres@db:5432/django_db
      - REDIS_URL=redis://redis:6379/0
    depends_on:
      - db
      - redis

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: django_db
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
    volumes:
      - postgres-data:/var/lib/postgresql/data

  redis:
    image: redis:alpine
    volumes:
      - redis-data:/data

  celery:
    build: .
    command: celery -A myproject worker -l info
    volumes:
      - .:/code
    environment:
      - DATABASE_URL=postgresql://postgres:postgres@db:5432/django_db
      - REDIS_URL=redis://redis:6379/0
    depends_on:
      - db
      - redis

  celery-beat:
    build: .
    command: celery -A myproject beat -l info
    volumes:
      - .:/code
    environment:
      - DATABASE_URL=postgresql://postgres:postgres@db:5432/django_db
      - REDIS_URL=redis://redis:6379/0
    depends_on:
      - db
      - redis

volumes:
  postgres-data:
  redis-data:
示例 3:React + Node.js + MongoDB + NGINX
version: "3.8"

services:
  frontend:
    build:
      context: ./frontend
      args:
        REACT_APP_API_URL: http://localhost/api
    volumes:
      - ./frontend:/app
      - /app/node_modules
    environment:
      - CHOKIDAR_USEPOLLING=true
    networks:
      - app-network

  backend:
    build: ./backend
    ports:
      - "5000:5000"
    volumes:
      - ./backend:/app
      - /app/node_modules
    environment:
      - MONGODB_URI=mongodb://mongo:27017/myapp
      - JWT_SECRET=dev-secret
    depends_on:
      - mongo
    networks:
      - app-network

  mongo:
    image: mongo:6
    ports:
      - "27017:27017"
    volumes:
      - mongo-data:/data/db
      - mongo-config:/data/configdb
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=secret
    networks:
      - app-network

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - frontend
      - backend
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

volumes:
  mongo-data:
  mongo-config:
示例 4:Spring Boot + MySQL + Adminer
version: "3.8"

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    environment:
      - SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/springdb?useSSL=false
      - SPRING_DATASOURCE_USERNAME=root
      - SPRING_DATASOURCE_PASSWORD=secret
      - SPRING_JPA_HIBERNATE_DDL_AUTO=update
    depends_on:
      db:
        condition: service_healthy
    networks:
      - spring-network

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: springdb
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - spring-network
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  adminer:
    image: adminer:latest
    ports:
      - "8081:8080"
    environment:
      ADMINER_DEFAULT_SERVER: db
    networks:
      - spring-network

networks:
  spring-network:

volumes:
  mysql-data:
示例 5:WordPress + MySQL + phpMyAdmin
version: "3.8"

services:
  wordpress:
    image: wordpress:latest
    ports:
      - "8000:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - wordpress-data:/var/www/html
    depends_on:
      - db
    networks:
      - wordpress-network

  db:
    image: mysql:8.0
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
      MYSQL_ROOT_PASSWORD: rootpassword
    volumes:
      - db-data:/var/lib/mysql
    networks:
      - wordpress-network

  phpmyadmin:
    image: phpmyadmin/phpmyadmin:latest
    ports:
      - "8080:80"
    environment:
      PMA_HOST: db
      PMA_USER: root
      PMA_PASSWORD: rootpassword
    depends_on:
      - db
    networks:
      - wordpress-network

networks:
  wordpress-network:

volumes:
  wordpress-data:
  db-data:
示例 6:Elasticsearch + Kibana + Logstash(ELK Stack)
version: "3.8"

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.10.0
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - xpack.security.enabled=false
    ports:
      - "9200:9200"
      - "9300:9300"
    volumes:
      - elasticsearch-data:/usr/share/elasticsearch/data
    networks:
      - elk

  logstash:
    image: docker.elastic.co/logstash/logstash:8.10.0
    container_name: logstash
    volumes:
      - ./logstash/pipeline:/usr/share/logstash/pipeline:ro
      - ./logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml:ro
    ports:
      - "5000:5000"
      - "9600:9600"
    environment:
      LS_JAVA_OPTS: "-Xmx256m -Xms256m"
    networks:
      - elk
    depends_on:
      - elasticsearch

  kibana:
    image: docker.elastic.co/kibana/kibana:8.10.0
    container_name: kibana
    ports:
      - "5601:5601"
    environment:
      ELASTICSEARCH_URL: http://elasticsearch:9200
      ELASTICSEARCH_HOSTS: http://elasticsearch:9200
    networks:
      - elk
    depends_on:
      - elasticsearch

networks:
  elk:
    driver: bridge

volumes:
  elasticsearch-data:
示例 7:GitLab + GitLab Runner
version: "3.8"

services:
  gitlab:
    image: gitlab/gitlab-ce:latest
    container_name: gitlab
    restart: unless-stopped
    hostname: gitlab.local
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'http://gitlab.local'
        gitlab_rails['gitlab_shell_ssh_port'] = 2222
    ports:
      - "80:80"
      - "443:443"
      - "2222:22"
    volumes:
      - gitlab-config:/etc/gitlab
      - gitlab-logs:/var/log/gitlab
      - gitlab-data:/var/opt/gitlab
    networks:
      - gitlab-network

  gitlab-runner:
    image: gitlab/gitlab-runner:latest
    container_name: gitlab-runner
    restart: unless-stopped
    volumes:
      - gitlab-runner-config:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - gitlab-network
    depends_on:
      - gitlab

networks:
  gitlab-network:

volumes:
  gitlab-config:
  gitlab-logs:
  gitlab-data:
  gitlab-runner-config:
示例 8:Jenkins + Docker-in-Docker
version: "3.8"

services:
  jenkins:
    image: jenkins/jenkins:lts
    container_name: jenkins
    user: root
    ports:
      - "8080:8080"
      - "50000:50000"
    volumes:
      - jenkins-data:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
      - /usr/bin/docker:/usr/bin/docker
    environment:
      - JAVA_OPTS=-Djenkins.install.runSetupWizard=false
    networks:
      - jenkins-network

  jenkins-agent:
    image: jenkins/inbound-agent:latest
    container_name: jenkins-agent
    environment:
      - JENKINS_URL=http://jenkins:8080
      - JENKINS_AGENT_NAME=agent1
      - JENKINS_SECRET=${AGENT_SECRET}
      - JENKINS_AGENT_WORKDIR=/home/jenkins/agent
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - jenkins-network
    depends_on:
      - jenkins

networks:
  jenkins-network:

volumes:
  jenkins-data:
示例 9:Prometheus + Grafana + Node Exporter
version: "3.8"

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
    networks:
      - monitoring

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=admin
      - GF_INSTALL_PLUGINS=grafana-piechart-panel
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning:ro
    networks:
      - monitoring
    depends_on:
      - prometheus

  node-exporter:
    image: prom/node-exporter:latest
    container_name: node-exporter
    ports:
      - "9100:9100"
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
    networks:
      - monitoring

networks:
  monitoring:

volumes:
  prometheus-data:
  grafana-data:
示例 10:RabbitMQ + 多个消费者
version: "3.8"

services:
  rabbitmq:
    image: rabbitmq:3-management-alpine
    container_name: rabbitmq
    ports:
      - "5672:5672"   # AMQP
      - "15672:15672" # Management UI
    environment:
      RABBITMQ_DEFAULT_USER: admin
      RABBITMQ_DEFAULT_PASS: secret
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq
      - ./rabbitmq/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf:ro
    networks:
      - messaging
    healthcheck:
      test: ["CMD", "rabbitmq-diagnostics", "ping"]
      interval: 30s
      timeout: 10s
      retries: 5

  producer:
    build: ./services/producer
    environment:
      RABBITMQ_URL: amqp://admin:secret@rabbitmq:5672
    depends_on:
      rabbitmq:
        condition: service_healthy
    networks:
      - messaging

  consumer-1:
    build: ./services/consumer
    environment:
      RABBITMQ_URL: amqp://admin:secret@rabbitmq:5672
      WORKER_ID: 1
    depends_on:
      rabbitmq:
        condition: service_healthy
    networks:
      - messaging
    deploy:
      replicas: 3

  consumer-2:
    build: ./services/consumer
    environment:
      RABBITMQ_URL: amqp://admin:secret@rabbitmq:5672
      WORKER_ID: 2
    depends_on:
      rabbitmq:
        condition: service_healthy
    networks:
      - messaging

networks:
  messaging:

volumes:
  rabbitmq-data:
示例 11:Traefik 反向代理
version: "3.8"

services:
  traefik:
    image: traefik:v2.10
    container_name: traefik
    command:
      - --api.insecure=true
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"  # Traefik dashboard
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro
      - ./traefik/dynamic:/etc/traefik/dynamic:ro
    networks:
      - traefik-network

  whoami:
    image: traefik/whoami
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.local`)"
      - "traefik.http.routers.whoami.entrypoints=web"
    networks:
      - traefik-network

  app:
    image: nginx:alpine
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app.rule=Host(`app.local`)"
      - "traefik.http.routers.app.entrypoints=web"
      - "traefik.http.services.app.loadbalancer.server.port=80"
    networks:
      - traefik-network

networks:
  traefik-network:
    driver: bridge
示例 12:MinIO + PostgreSQL 备份
version: "3.8"

services:
  minio:
    image: minio/minio:latest
    container_name: minio
    command: server /data --console-address ":9001"
    ports:
      - "9000:9000"
      - "9001:9001"
    environment:
      MINIO_ROOT_USER: minioadmin
      MINIO_ROOT_PASSWORD: minioadmin
    volumes:
      - minio-data:/data
    networks:
      - storage
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3

  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: secret
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - storage

  backup:
    image: postgres:15-alpine
    environment:
      POSTGRES_HOST: postgres
      POSTGRES_DB: myapp
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: secret
      MINIO_ENDPOINT: minio:9000
      MINIO_ACCESS_KEY: minioadmin
      MINIO_SECRET_KEY: minioadmin
    volumes:
      - ./scripts/backup.sh:/backup.sh:ro
    entrypoint: ["/bin/sh", "/backup.sh"]
    depends_on:
      - postgres
      - minio
    networks:
      - storage

networks:
  storage:

volumes:
  minio-data:
  postgres-data:
示例 13:Apache Kafka + Zookeeper
version: "3.8"

services:
  zookeeper:
    image: confluentinc/cp-zookeeper:latest
    container_name: zookeeper
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000
    ports:
      - "2181:2181"
    volumes:
      - zookeeper-data:/var/lib/zookeeper/data
      - zookeeper-logs:/var/lib/zookeeper/log
    networks:
      - kafka-network

  kafka:
    image: confluentinc/cp-kafka:latest
    container_name: kafka
    depends_on:
      - zookeeper
    ports:
      - "9092:9092"
      - "29092:29092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
    volumes:
      - kafka-data:/var/lib/kafka/data
    networks:
      - kafka-network

  kafka-ui:
    image: provectuslabs/kafka-ui:latest
    container_name: kafka-ui
    depends_on:
      - kafka
    ports:
      - "8080:8080"
    environment:
      KAFKA_CLUSTERS_0_NAME: local
      KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092
      KAFKA_CLUSTERS_0_ZOOKEEPER: zookeeper:2181
    networks:
      - kafka-network

networks:
  kafka-network:

volumes:
  zookeeper-data:
  zookeeper-logs:
  kafka-data:
示例 14:Keycloak + PostgreSQL(身份与访问管理)
version: "3.8"

services:
  postgres:
    image: postgres:15-alpine
    container_name: keycloak-db
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloak
      POSTGRES_PASSWORD: password
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - keycloak-network

  keycloak:
    image: quay.io/keycloak/keycloak:latest
    container_name: keycloak
    environment:
      KC_DB: postgres
      KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
      KC_DB_USERNAME: keycloak
      KC_DB_PASSWORD: password
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: admin
    command: start-dev
    ports:
      - "8080:8080"
    depends_on:
      - postgres
    networks:
      - keycloak-network

networks:
  keycloak-network:

volumes:
  postgres-data:
示例 15:Portainer(Docker 管理界面)
version: "3.8"

services:
  portainer:
    image: portainer/portainer-ce:latest
    container_name: portainer
    restart: unless-stopped
    ports:
      - "9000:9000"
      - "8000:8000"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer-data:/data
    networks:
      - portainer-network

networks:
  portainer-network:

volumes:
  portainer-data:
示例 16:SonarQube + PostgreSQL(代码质量)
version: "3.8"

services:
  sonarqube:
    image: sonarqube:community
    container_name: sonarqube
    depends_on:
      - db
    environment:
      SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar
      SONAR_JDBC_USERNAME: sonar
      SONAR_JDBC_PASSWORD: sonar
    volumes:
      - sonarqube-conf:/opt/sonarqube/conf
      - sonarqube-data:/opt/sonarqube/data
      - sonarqube-logs:/opt/sonarqube/logs
      - sonarqube-extensions:/opt/sonarqube/extensions
    ports:
      - "9000:9000"
    networks:
      - sonarqube-network

  db:
    image: postgres:15-alpine
    container_name: sonarqube-db
    environment:
      POSTGRES_USER: sonar
      POSTGRES_PASSWORD: sonar
      POSTGRES_DB: sonar
    volumes:
      - postgresql-data:/var/lib/postgresql/data
    networks:
      - sonarqube-network

networks:
  sonarqube-network:

volumes:
  sonarqube-conf:
  sonarqube-data:
  sonarqube-logs:
  sonarqube-extensions:
  postgresql-data:

最佳实践

服务配置
  1. 使用特定镜像标签:在生产环境中避免使用 latest
  2. 健康检查:始终为关键服务定义健康检查
  3. 资源限制:在生产环境中设置 CPU 和内存限制
  4. 重启策略:使用适当的重启策略
  5. 环境变量:使用 .env 文件存放敏感数据
  6. 命名卷:使用命名卷持久化数据
  7. 网络隔离:分离前端和后端网络
  8. 日志配置:设置恰当的日志轮换
开发工作流
  1. 热重载:将源代码挂载为卷,以便实时更新
  2. 调试端口:在开发环境中公开调试器端口
  3. 覆盖文件:使用 compose.override.yaml 配置本地设置
  4. 构建缓存:合理组织 Dockerfile,以提高缓存效率
  5. 职责分离:每个容器运行一个进程
  6. 服务命名:使用描述清晰且一致的服务名称
安全
  1. 机密管理:使用 Docker secrets 或外部机密管理器
  2. 非 Root 用户:以非 Root 用户身份运行容器
  3. 只读文件系统:尽可能将卷挂载为只读
  4. 网络分段:使用多个网络实现隔离
  5. 环境隔离:切勿提交包含敏感信息的 .env 文件
  6. 镜像扫描:扫描镜像中的漏洞
  7. 精简基础镜像:使用 Alpine 或 distroless 镜像
生产部署
  1. 镜像版本管理:使用语义化版本为镜像打标签
  2. 滚动更新:配置渐进式发布策略
  3. 监控:集成监控解决方案
  4. 备份策略:实施自动备份
  5. 高可用性:部署关键服务的副本
  6. 负载均衡:使用反向代理分配负载
  7. 配置管理:将配置外置
  8. 灾难恢复:测试备份和恢复流程

故障排除

常见问题

服务无法通信

  • 检查网络配置
  • 确认服务名称正确
  • 确保服务位于同一网络
  • 检查防火墙规则

卷无法持久化

  • 确认已定义命名卷
  • 检查卷挂载路径
  • 确保权限正确
  • 检查 Docker 卷驱动程序

服务未通过健康检查

  • 增加 start_period
  • 确认健康检查命令
  • 检查服务日志
  • 确保依赖项已就绪

端口冲突

  • 检查端口是否已有服务占用
  • 使用不同的主机端口
  • 检查端口映射语法

构建失败

  • 清除构建缓存:docker compose build --no-cache
  • 检查 Dockerfile 语法
  • 确认构建上下文
  • 检查构建参数
调试命令
# View detailed container information
docker compose ps -a
docker compose logs -f service-name
docker inspect container-name

# Execute commands in running containers
docker compose exec service-name sh
docker compose exec service-name env

# Check network connectivity
docker compose exec service-name ping other-service
docker compose exec service-name netstat -tulpn

# Review configuration
docker compose config
docker compose config --services
docker compose config --volumes

# Clean up resources
docker compose down -v
docker system prune -a --volumes

高级用法

用于优化的多阶段构建
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: production
    # Dockerfile uses multi-stage builds
# Development stage
FROM node:18-alpine AS development
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm", "run", "dev"]

# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

# Production stage
FROM node:18-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
EXPOSE 3000
CMD ["node", "dist/index.js"]
针对不同环境的部署
# Development
docker compose up

# Staging
docker compose -f compose.yaml -f compose.staging.yaml up

# Production
docker compose -f compose.yaml -f compose.prod.yaml up -d

# With environment file
docker compose --env-file .env.prod -f compose.yaml -f compose.prod.yaml up -d
扩展服务
# Scale specific service
docker compose up -d --scale worker=5

# Scale multiple services
docker compose up -d --scale worker=5 --scale consumer=3
使用 Profiles 有条件地启用服务
services:
  web:
    image: nginx
    # Always starts

  debug:
    image: debug-tools
    profiles:
      - debug  # Only starts with --profile debug

  test:
    build: .
    profiles:
      - test   # Only starts with --profile test
# Start with debug profile
docker compose --profile debug up

# Start with multiple profiles
docker compose --profile debug --profile test up

快速参考

基本命令
# Start and manage
docker compose up -d                    # Start detached
docker compose down                     # Stop and remove
docker compose restart                  # Restart all
docker compose stop                     # Stop without removing

# Build and pull
docker compose build                    # Build all images
docker compose pull                     # Pull all images
docker compose build --no-cache        # Clean build

# View and monitor
docker compose ps                       # List containers
docker compose logs -f                  # Follow logs
docker compose top                      # Running processes
docker compose events                   # Real-time events

# Execute and debug
docker compose exec service sh          # Interactive shell
docker compose run --rm service cmd     # One-off command
文件结构
project/
├── compose.yaml              # Base configuration
├── compose.override.yaml     # Local overrides (auto-loaded)
├── compose.prod.yaml         # Production config
├── compose.staging.yaml      # Staging config
├── .env                      # Default environment
├── .env.prod                 # Production environment
├── services/
│   ├── frontend/
│   │   ├── Dockerfile
│   │   └── src/
│   ├── backend/
│   │   ├── Dockerfile
│   │   └── src/
│   └── worker/
│       ├── Dockerfile
│       └── src/
└── docker/
    ├── nginx/
    │   └── nginx.conf
    └── scripts/
        └── init.sql

资源


技能版本:1.0.0 最后更新:2025 年 10 月 技能类别:DevOps、容器编排、应用部署 兼容版本:Docker Compose v3.8+、Docker Engine 20.10+

评论

支持 Markdown