Docker Compose 生产环境配置

Docker Compose 生产环境配置 本文介绍 Docker Compose 在生产环境中的最佳实践,包括 Compose 文件编写、网络配置、持久化存储以及安全设置。 概述 Docker Compose 是定义和运行多容器 Docker 应用的工具。本文将介绍如何在生产环境中正确配置 Doc

Docker Compose 生产环境配置

本文介绍 Docker Compose 在生产环境中的最佳实践,包括 Compose 文件编写、网络配置、持久化存储以及安全设置。

概述

Docker Compose 是定义和运行多容器 Docker 应用的工具。本文将介绍如何在生产环境中正确配置 Docker Compose,确保应用的稳定性、安全性和可维护性。

Compose 文件结构

基础结构示例

version: '3.8'

services:
  app:
    image: myapp:latest
    container_name: myapp
    restart: unless-stopped
    environment:
      - NODE_ENV=production
      - DB_HOST=db
    ports:
      - "8080:8080"
    networks:
      - backend
      - frontend
    depends_on:
      - db
      - cache
    volumes:
      - app-data:/app/data
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  db:
    image: postgres:15-alpine
    container_name: myapp-db
    restart: unless-stopped
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: dbuser
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    volumes:
      - db-data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    networks:
      - backend
    secrets:
      - db_password

  cache:
    image: redis:7-alpine
    container_name: myapp-cache
    restart: unless-stopped
    command: redis-server --requirepass ${REDIS_PASSWORD}
    volumes:
      - cache-data:/data
    networks:
      - backend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # 禁止外部访问

volumes:
  app-data:
    driver: local
  db-data:
    driver: local
  cache-data:
    driver: local

secrets:
  db_password:
    file: ./secrets/db_password.txt

生产环境配置要点

1. 重启策略

services:
  app:
    restart: unless-stopped  # 推荐生产环境使用
    # 其他选项:
    # restart: always         # 总是重启(包括手动停止后)
    # restart: on-failure     # 仅在失败时重启
    # restart: no             # 不自动重启(开发环境)

2. 资源限制

services:
  app:
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G
        reservations:
          cpus: '1'
          memory: 1G

3. 健康检查

services:
  web:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    
  db:
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

网络配置

自定义网络

networks:
  # 前端网络(可外部访问)
  frontend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24
  
  # 后端网络(仅内部通信)
  backend:
    driver: bridge
    internal: true
    ipam:
      config:
        - subnet: 172.20.1.0/24
  
  # 使用现有网络
  existing:
    external: true
    name: my-existing-network

服务网络配置

services:
  proxy:
    image: nginx:alpine
    networks:
      frontend:
        ipv4_address: 172.20.0.10
      backend:
        aliases:
          - gateway
  
  app:
    image: myapp:latest
    networks:
      - backend
    expose:
      - "8080"  # 仅内部暴露,不映射到主机

持久化存储

命名卷

volumes:
  postgres-data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /data/postgres

services:
  db:
    volumes:
      - postgres-data:/var/lib/postgresql/data

绑定挂载

services:
  app:
    volumes:
      # 配置目录(只读)
      - ./config:/app/config:ro
      
      # 数据目录
      - /var/data/app:/app/data
      
      # 日志目录
      - /var/log/app:/app/logs
      
      # 临时目录
      - type: tmpfs
        target: /tmp
        tmpfs:
          size: 100M

环境变量管理

使用 .env 文件

# .env 文件(不提交到版本控制)
NODE_ENV=production
DB_HOST=db
DB_PORT=5432
DB_NAME=myapp
DB_USER=appuser
DB_PASSWORD=secretpassword
REDIS_PASSWORD=redispass
APP_PORT=8080
# docker-compose.yml
services:
  app:
    image: myapp:latest
    environment:
      - NODE_ENV=${NODE_ENV}
      - DB_HOST=${DB_HOST}
      - DB_PORT=${DB_PORT}
    ports:
      - "${APP_PORT}:8080"

使用 Secrets

# docker-compose.yml
services:
  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password
      - db_root_password

secrets:
  db_password:
    file: ./secrets/db_password.txt
  db_root_password:
    file: ./secrets/db_root_password.txt

多环境配置

基础配置 + 环境覆盖

# docker-compose.yml(基础配置)
version: '3.8'

services:
  app:
    image: myapp:latest
    ports:
      - "8080:8080"
    environment:
      - LOG_LEVEL=info
# docker-compose.prod.yml(生产环境覆盖)
version: '3.8'

services:
  app:
    restart: unless-stopped
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G
    environment:
      - NODE_ENV=production
      - LOG_LEVEL=warn
# docker-compose.dev.yml(开发环境覆盖)
version: '3.8'

services:
  app:
    build: .
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - LOG_LEVEL=debug

启动命令

# 开发环境
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up

# 生产环境
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

# 或使用环境变量
COMPOSE_FILE=docker-compose.yml:docker-compose.prod.yml docker-compose up -d

日志管理

日志配置

services:
  app:
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "10"
        labels: "service_name,environment"
        env: "OS_VERSION"
  
  nginx:
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://logs.example.com:514"
        tag: "nginx-{{.Name}}"

集中式日志

services:
  fluentd:
    image: fluent/fluentd:v1.16
    volumes:
      - ./fluentd/conf:/fluentd/etc
    ports:
      - "24224:24224"
  
  app:
    image: myapp:latest
    logging:
      driver: fluentd
      options:
        fluentd-address: localhost:24224
        tag: docker.myapp

安全加固

以非 root 用户运行

services:
  app:
    image: myapp:latest
    user: "1000:1000"
    read_only: true
    tmpfs:
      - /tmp
      - /var/cache

安全选项

services:
  app:
    image: myapp:latest
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    sysctls:
      - net.core.somaxconn=1024

只读根文件系统

services:
  nginx:
    image: nginx:alpine
    read_only: true
    tmpfs:
      - /var/cache/nginx:noexec,nosuid,size=100m
      - /var/run:noexec,nosuid,size=100m
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./html:/usr/share/nginx/html:ro

监控与告警

Prometheus 监控

services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
    ports:
      - "9090:9090"
  
  grafana:
    image: grafana/grafana:latest
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana/dashboards:/etc/grafana/provisioning/dashboards:ro
    ports:
      - "3000:3000"
    depends_on:
      - prometheus

备份策略

数据备份

services:
  backup:
    image: offen/docker-volume-backup:latest
    environment:
      BACKUP_CRON_EXPRESSION: "0 2 * * *"
      BACKUP_RETENTION_DAYS: "30"
      AWS_S3_BUCKET_NAME: my-backup-bucket
      AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY}
      AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_KEY}
    volumes:
      - db-data:/backup/db-data:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro

常见问题处理

时区设置

services:
  app:
    image: myapp:latest
    environment:
      - TZ=Asia/Shanghai
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro

DNS 配置

services:
  app:
    image: myapp:latest
    dns:
      - 8.8.8.8
      - 8.8.4.4
    dns_search:
      - example.com
    dns_options:
      - ndots:1

部署命令

# 启动服务
docker-compose up -d

# 查看日志
docker-compose logs -f

# 查看特定服务日志
docker-compose logs -f app

# 重启服务
docker-compose restart app

# 更新服务
docker-compose pull
docker-compose up -d

# 停止并删除
docker-compose down

# 停止并删除卷(清理数据)
docker-compose down -v

# 扩展服务实例
docker-compose up -d --scale app=3

总结

本文介绍了 Docker Compose 在生产环境的配置方法:

  1. 基础配置:服务定义、重启策略、健康检查
  2. 网络配置:隔离前端和后端网络,提高安全性
  3. 持久化存储:命名卷和绑定挂载的合理使用
  4. 环境管理:.env 文件和 Secrets 的安全管理
  5. 多环境支持:基础配置 + 环境特定覆盖
  6. 安全加固:非 root 用户、只读文件系统、安全选项
  7. 运维管理:日志、监控、备份策略

通过遵循这些最佳实践,可以在生产环境中安全、稳定地运行 Docker Compose 应用。

Comment