Docker Compose 服务配置详解

概述

在 Docker Compose 中,services 是配置文件的核心部分,定义了应用程序中的各个服务。本文将深入探讨服务配置的各个方面,包括镜像配置、端口映射、卷挂载、环境变量等。

服务定义基础

基本服务结构

version: '3.8'

services:
  service_name:
    # 服务配置选项
    image: image_name:tag
    container_name: custom_container_name
    restart: always

镜像配置

1. 使用现有镜像

services:
  web:
    image: nginx:1.21-alpine

  database:
    image: postgres:13

  cache:
    image: redis:6-alpine

2. 构建自定义镜像

简单构建

services:
  app:
    build: .  # 使用当前目录的 Dockerfile

详细构建配置

services:
  app:
    build:
      context: ./app          # 构建上下文目录
      dockerfile: Dockerfile.prod  # 指定 Dockerfile
      args:                   # 构建参数
        - NODE_ENV=production
        - API_URL=https://api.example.com
      target: production      # 多阶段构建目标
      cache_from:            # 缓存来源
        - myapp:latest
      labels:                # 镜像标签
        - "com.example.version=1.0"
        - "com.example.environment=production"

构建参数示例

# Dockerfile
FROM node:14-alpine
ARG NODE_ENV=development
ARG API_URL=http://localhost:3000

ENV NODE_ENV=$NODE_ENV
ENV REACT_APP_API_URL=$API_URL

WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

EXPOSE 3000
CMD ["npm", "start"]

端口映射

1. 基本端口映射

services:
  web:
    image: nginx
    ports:
      - "80:80"           # 主机端口:容器端口
      - "443:443"
      - "8080:80"         # 映射到不同端口

2. 高级端口配置

services:
  web:
    image: nginx
    ports:
      - "80:80"                    # 绑定到所有接口
      - "127.0.0.1:8080:80"       # 绑定到特定 IP
      - "8000-8010:8000-8010"     # 端口范围映射
      - target: 80                 # 长格式配置
        published: 8080
        protocol: tcp
        mode: host

3. 暴露端口(不映射到主机)

services:
  api:
    image: myapi
    expose:
      - "3000"    # 只在容器间可访问
      - "3001"

卷挂载配置

1. 绑定挂载

services:
  web:
    image: nginx
    volumes:
      - ./html:/usr/share/nginx/html:ro     # 只读挂载
      - ./config:/etc/nginx/conf.d:rw       # 读写挂载(默认)
      - /var/log/nginx:/var/log/nginx       # 绝对路径挂载

2. 命名卷

version: '3.8'

services:
  database:
    image: postgres:13
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - postgres_backup:/backup

volumes:
  postgres_data:
    driver: local
  postgres_backup:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /host/backup/path

3. 临时文件系统

services:
  app:
    image: myapp
    tmpfs:
      - /tmp
      - /var/cache
    # 或使用长格式
    tmpfs:
      - type: tmpfs
        target: /tmp
        tmpfs:
          size: 100M

4. 高级卷配置

services:
  app:
    image: myapp
    volumes:
      - type: bind
        source: ./app
        target: /usr/src/app
        read_only: true
      - type: volume
        source: data_volume
        target: /data
        volume:
          nocopy: true
      - type: tmpfs
        target: /tmp
        tmpfs:
          size: 100M
          mode: 1777

volumes:
  data_volume:

环境变量配置

1. 直接定义环境变量

services:
  app:
    image: myapp
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
      - DEBUG=false
    # 或使用映射格式
    environment:
      NODE_ENV: production
      DATABASE_URL: postgresql://user:pass@db:5432/mydb
      DEBUG: "false"  # 注意:所有值都是字符串

2. 从文件加载环境变量

services:
  app:
    image: myapp
    env_file:
      - .env
      - .env.local
      - ./config/.env.production

.env 文件示例

# .env
NODE_ENV=production
DATABASE_URL=postgresql://user:password@db:5432/mydb
REDIS_URL=redis://redis:6379
SECRET_KEY=your-secret-key
DEBUG=false

3. 环境变量优先级

  1. Compose 文件中的 environment
  2. Shell 环境变量
  3. env_file 中的变量
  4. Dockerfile 中的 ENV

网络配置

1. 默认网络

services:
  web:
    image: nginx
  api:
    image: myapi
  # 默认情况下,所有服务都在同一个网络中

2. 自定义网络

version: '3.8'

services:
  web:
    image: nginx
    networks:
      - frontend

  api:
    image: myapi
    networks:
      - frontend
      - backend

  database:
    image: postgres
    networks:
      - backend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # 内部网络,不能访问外部

3. 网络别名

services:
  api:
    image: myapi
    networks:
      backend:
        aliases:
          - api-server
          - backend-api

networks:
  backend:

4. 外部网络

services:
  app:
    image: myapp
    networks:
      - existing_network

networks:
  existing_network:
    external: true

依赖关系配置

1. 基本依赖

services:
  web:
    image: nginx
    depends_on:
      - api
      - database

  api:
    image: myapi
    depends_on:
      - database
      - redis

  database:
    image: postgres

  redis:
    image: redis

2. 条件依赖(需要 Compose 文件版本 2.1)

version: '2.1'

services:
  web:
    image: nginx
    depends_on:
      api:
        condition: service_healthy
      database:
        condition: service_started

  api:
    image: myapi
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  database:
    image: postgres

资源限制

1. 内存和 CPU 限制

services:
  app:
    image: myapp
    deploy:
      resources:
        limits:
          cpus: '0.5'      # 限制 CPU 使用
          memory: 512M     # 限制内存使用
        reservations:
          cpus: '0.25'     # 保留 CPU
          memory: 256M     # 保留内存

2. 设备限制

services:
  app:
    image: myapp
    deploy:
      resources:
        limits:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]

健康检查

services:
  web:
    image: nginx
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 30s      # 检查间隔
      timeout: 10s       # 超时时间
      retries: 3         # 重试次数
      start_period: 40s  # 启动等待时间
      disable: false     # 是否禁用健康检查

  api:
    image: myapi
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"]
      interval: 1m
      timeout: 30s
      retries: 5
      start_period: 30s

重启策略

services:
  web:
    image: nginx
    restart: always           # 总是重启

  api:
    image: myapi
    restart: unless-stopped   # 除非手动停止

  worker:
    image: myworker
    restart: on-failure       # 失败时重启

  temp:
    image: temp-service
    restart: "no"             # 不重启(默认)

日志配置

services:
  web:
    image: nginx
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  api:
    image: myapi
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://192.168.1.42:123"
        tag: "api-service"

  app:
    image: myapp
    logging:
      driver: "none"  # 禁用日志

安全配置

1. 用户和权限

services:
  app:
    image: myapp
    user: "1000:1000"        # 指定用户 ID 和组 ID
    # user: "username"       # 或使用用户名

    # 只读根文件系统
    read_only: true
    tmpfs:
      - /tmp
      - /var/cache

    # 权限控制
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE

    # 安全选项
    security_opt:
      - no-new-privileges:true
      - apparmor:unconfined

2. 特权和设备

services:
  privileged_app:
    image: myapp
    privileged: true         # 特权模式(谨慎使用)

  device_app:
    image: myapp
    devices:
      - "/dev/sda:/dev/xvda:rwm"  # 设备映射

完整示例:Web 应用栈

version: '3.8'

services:
  # 反向代理
  nginx:
    image: nginx:alpine
    container_name: web-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
      - static_files:/usr/share/nginx/html/static:ro
    depends_on:
      - web
    networks:
      - frontend
    restart: unless-stopped
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # Web 应用
  web:
    build:
      context: ./web
      dockerfile: Dockerfile.prod
      args:
        - NODE_ENV=production
    container_name: web-app
    environment:
      - NODE_ENV=production
      - API_URL=http://api:3000
      - REDIS_URL=redis://redis:6379
    env_file:
      - .env.production
    volumes:
      - static_files:/app/static
    depends_on:
      - api
      - redis
    networks:
      - frontend
      - backend
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      resources:
        limits:
          memory: 512M
        reservations:
          memory: 256M

  # API 服务
  api:
    build:
      context: ./api
      target: production
    container_name: api-server
    environment:
      DATABASE_URL: postgresql://postgres:password@db:5432/myapp
      REDIS_URL: redis://redis:6379
    depends_on:
      - db
      - redis
    networks:
      - backend
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:3000/api/health || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  # 数据库
  db:
    image: postgres:13-alpine
    container_name: postgres-db
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    networks:
      - backend
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

  # 缓存
  redis:
    image: redis:6-alpine
    container_name: redis-cache
    command: redis-server --appendonly yes --requirepass mypassword
    volumes:
      - redis_data:/data
    networks:
      - backend
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 3

# 卷定义
volumes:
  postgres_data:
    driver: local
  redis_data:
    driver: local
  static_files:
    driver: local

# 网络定义
networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true

最佳实践

1. 服务设计原则

  • 单一职责: 每个服务只负责一个功能
  • 无状态: 尽量设计无状态服务
  • 松耦合: 服务间通过网络通信,避免文件系统依赖

2. 配置管理

  • 使用环境变量管理配置
  • 敏感信息使用 secrets 或外部配置管理
  • 不同环境使用不同的 compose 文件

3. 资源优化

  • 合理设置资源限制
  • 使用多阶段构建减小镜像大小
  • 选择合适的基础镜像(如 alpine)

4. 安全考虑

  • 不使用 root 用户运行应用
  • 启用只读文件系统
  • 最小化容器权限
  • 定期更新基础镜像

总结

Docker Compose 服务配置提供了丰富的选项来定义和管理容器化应用程序。通过合理配置镜像、端口、卷、网络、环境变量等,可以构建出稳定、安全、高效的多容器应用系统。掌握这些配置选项是使用 Docker Compose 的基础。

powered by Gitbook© 2025 编外计划 | 最后修改: 2025-08-29 15:40:15

results matching ""

    No results matching ""