DockerCompose生产部署Skill docker-compose-production

这个技能专门用于在生產环境中部署和管理Docker Compose應用,涵盖安全加固、资源优化、健康监控、日志管理、高可用性配置等關鍵領域。關鍵詞:Docker Compose, 生產部署, 容器化, DevOps, 雲計算, 安全, 監控, 備份。

Docker/K8s 0 次安装 0 次浏览 更新于 3/25/2026

名称: docker-compose-production 用户可调用: false 描述: 当部署Docker Compose应用到生产环境时使用,包括安全加固、资源管理、健康检查、日志记录、监控和高可用性模式。 允许工具: [Bash, Read]

Docker Compose 生产部署

生产就绪的Docker Compose配置,包含安全、可靠性和可扩展性的最佳实践。

生产就绪基础模板

一个全面的生产模板,包含基本配置:

版本: '3.8'

服务:
  nginx:
    图像: nginx:1.25-alpine
    容器名称: production-nginx
    重启: unless-stopped
    端口:
      - "80:80"
      - "443:443"
    卷:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
      - nginx-cache:/var/cache/nginx
      - nginx-logs:/var/log/nginx
    网络:
      - frontend
    健康检查:
      测试: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"]
      间隔: 30s
      超时: 10s
      重试: 3
      启动期: 40s
    日志:
      驱动: "json-file"
      选项:
        最大大小: "10m"
        最大文件: "3"
    部署:
      资源:
        限制:
          cpus: '1.0'
          内存: 512M
        保留:
          cpus: '0.5'
          内存: 256M

  api:
    图像: mycompany/api:${API_VERSION:-latest}
    容器名称: production-api
    重启: unless-stopped
    网络:
      - frontend
      - backend
    环境:
      NODE_ENV: production
      DATABASE_URL: postgresql://postgres:5432/production_db
      REDIS_URL: redis://cache:6379
      LOG_LEVEL: ${LOG_LEVEL:-info}
      PORT: 3000
    环境文件:
      - .env.production
    秘密:
      - db_password
      - jwt_secret
    健康检查:
      测试: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/health"]
      间隔: 30s
      超时: 10s
      重试: 3
      启动期: 60s
    依赖:
      数据库:
        条件: service_healthy
      缓存:
        条件: service_healthy
    日志:
      驱动: "json-file"
      选项:
        最大大小: "10m"
        最大文件: "5"
    部署:
      资源:
        限制:
          cpus: '2.0'
          内存: 2G
        保留:
          cpus: '1.0'
          内存: 1G

  worker:
    图像: mycompany/worker:${WORKER_VERSION:-latest}
    容器名称: production-worker
    重启: unless-stopped
    网络:
      - backend
    环境:
      NODE_ENV: production
      DATABASE_URL: postgresql://postgres:5432/production_db
      REDIS_URL: redis://cache:6379
      QUEUE_NAME: ${QUEUE_NAME:-default}
    环境文件:
      - .env.production
    秘密:
      - db_password
    依赖:
      数据库:
        条件: service_healthy
      缓存:
        条件: service_healthy
    日志:
      驱动: "json-file"
      选项:
        最大大小: "10m"
        最大文件: "5"
    部署:
      副本: 3
      资源:
        限制:
          cpus: '1.0'
          内存: 1G
        保留:
          cpus: '0.5'
          内存: 512M

  数据库:
    图像: postgres:15-alpine
    容器名称: production-db
    重启: unless-stopped
    网络:
      - backend
    环境:
      POSTGRES_DB: production_db
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
      POSTGRES_INITDB_ARGS: "-E UTF8 --locale=en_US.UTF-8"
    秘密:
      - db_password
    卷:
      - postgres-data:/var/lib/postgresql/data
      - ./db/init:/docker-entrypoint-initdb.d:ro
      - postgres-logs:/var/log/postgresql
    健康检查:
      测试: ["CMD-SHELL", "pg_isready -U postgres -d production_db"]
      间隔: 10s
      超时: 5s
      重试: 5
      启动期: 30s
    命令:
      - "postgres"
      - "-c"
      - "max_connections=200"
      - "-c"
      - "shared_buffers=256MB"
      - "-c"
      - "effective_cache_size=1GB"
      - "-c"
      - "maintenance_work_mem=64MB"
      - "-c"
      - "checkpoint_completion_target=0.9"
      - "-c"
      - "wal_buffers=16MB"
      - "-c"
      - "default_statistics_target=100"
      - "-c"
      - "random_page_cost=1.1"
      - "-c"
      - "effective_io_concurrency=200"
      - "-c"
      - "work_mem=1MB"
      - "-c"
      - "min_wal_size=1GB"
      - "-c"
      - "max_wal_size=4GB"
    日志:
      驱动: "json-file"
      选项:
        最大大小: "10m"
        最大文件: "5"
    部署:
      资源:
        限制:
          cpus: '2.0'
          内存: 2G
        保留:
          cpus: '1.0'
          内存: 1G

  缓存:
    图像: redis:7-alpine
    容器名称: production-cache
    重启: unless-stopped
    网络:
      - backend
    命令: >
      redis-server
      --appendonly yes
      --appendfsync everysec
      --maxmemory 512mb
      --maxmemory-policy allkeys-lru
      --requirepass ${REDIS_PASSWORD}
    卷:
      - redis-data:/data
    健康检查:
      测试: ["CMD", "redis-cli", "--raw", "incr", "ping"]
      间隔: 10s
      超时: 5s
      重试: 5
      启动期: 20s
    日志:
      驱动: "json-file"
      选项:
        最大大小: "10m"
        最大文件: "3"
    部署:
      资源:
        限制:
          cpus: '1.0'
          内存: 768M
        保留:
          cpus: '0.5'
          内存: 512M

  备份:
    图像: prodrigestivill/postgres-backup-local:15-alpine
    容器名称: production-backup
    重启: unless-stopped
    网络:
      - backend
    环境:
      POSTGRES_HOST: 数据库
      POSTGRES_DB: production_db
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
      SCHEDULE: "@daily"
      BACKUP_KEEP_DAYS: 7
      BACKUP_KEEP_WEEKS: 4
      BACKUP_KEEP_MONTHS: 6
      HEALTHCHECK_PORT: 8080
    秘密:
      - db_password
    卷:
      - ./backups:/backups
    依赖:
      数据库:
        条件: service_healthy

网络:
  frontend:
    驱动: bridge
  backend:
    驱动: bridge
    内部: true

卷:
  postgres-data:
    驱动: local
    驱动选项:
      类型: none
      o: bind
      设备: /data/postgres
  redis-data:
    驱动: local
  nginx-cache:
    驱动: local
  nginx-logs:
    驱动: local
  postgres-logs:
    驱动: local

秘密:
  db_password:
    文件: ./secrets/db_password.txt
  jwt_secret:
    文件: ./secrets/jwt_secret.txt

安全加固

生产安全配置:

版本: '3.8'

服务:
  web:
    图像: nginx:1.25-alpine
    重启: unless-stopped
    只读: true
    tmpfs:
      - /var/cache/nginx
      - /var/run
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    security_opt:
      - no-new-privileges:true
      - seccomp:./security/seccomp-profile.json
    用户: "nginx:nginx"
    网络:
      - frontend
    端口:
      - "80:80"
      - "443:443"
    卷:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro

  api:
    图像: mycompany/api:${VERSION}
    重启: unless-stopped
    只读: true
    tmpfs:
      - /tmp
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
      - seccomp:./security/seccomp-profile.json
    用户: "1000:1000"
    网络:
      - frontend
      - backend
    环境:
      NODE_ENV: production
    环境文件:
      - .env.production
    秘密:
      - 源: db_password
        目标: /run/secrets/db_password
        模式: 0400
      - 源: api_key
        目标: /run/secrets/api_key
        模式: 0400

  数据库:
    图像: postgres:15-alpine
    重启: unless-stopped
    只读: true
    tmpfs:
      - /tmp
      - /run/postgresql
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - DAC_OVERRIDE
      - FOWNER
      - SETGID
      - SETUID
    security_opt:
      - no-new-privileges:true
    用户: "postgres:postgres"
    网络:
      - backend
    环境:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    秘密:
      - 源: db_password
        模式: 0400
    卷:
      - postgres-data:/var/lib/postgresql/data

网络:
  frontend:
    驱动: bridge
    驱动选项:
      com.docker.network.bridge.enable_icc: "false"
  backend:
    驱动: bridge
    内部: true

卷:
  postgres-data:

秘密:
  db_password:
    文件: ./secrets/db_password.txt
  api_key:
    文件: ./secrets/api_key.txt

资源限制和保留

全面资源管理:

版本: '3.8'

服务:
  web:
    图像: nginx:alpine
    重启: unless-stopped
    部署:
      资源:
        限制:
          cpus: '0.50'
          内存: 256M
          pids: 100
        保留:
          cpus: '0.25'
          内存: 128M
    ulimits:
      nofile:
        软: 1024
        硬: 2048
      nproc:
        软: 64
        硬: 128

  api:
    图像: node:18-alpine
    重启: unless-stopped
    部署:
      资源:
        限制:
          cpus: '2.0'
          内存: 2G
          pids: 200
        保留:
          cpus: '1.0'
          内存: 1G
    ulimits:
      nofile:
        软: 4096
        硬: 8192
      nproc:
        软: 256
        硬: 512

  数据库:
    图像: postgres:15-alpine
    重启: unless-stopped
    部署:
      资源:
        限制:
          cpus: '4.0'
          内存: 4G
          pids: 500
        保留:
          cpus: '2.0'
          内存: 2G
    ulimits:
      nofile:
        软: 8192
        硬: 16384
    shm_size: '256mb'
    卷:
      - postgres-data:/var/lib/postgresql/data

  缓存:
    图像: redis:7-alpine
    重启: unless-stopped
    部署:
      资源:
        限制:
          cpus: '1.0'
          内存: 1G
        保留:
          cpus: '0.5'
          内存: 512M
    sysctls:
      net.core.somaxconn: 1024
    卷:
      - redis-data:/data

卷:
  postgres-data:
  redis-data:

高可用性配置

多个副本与负载均衡:

版本: '3.8'

服务:
  负载均衡器:
    图像: nginx:alpine
    重启: unless-stopped
    端口:
      - "80:80"
      - "443:443"
    卷:
      - ./nginx/nginx-lb.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
    网络:
      - frontend
    健康检查:
      测试: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"]
      间隔: 10s
      超时: 5s
      重试: 3
    部署:
      资源:
        限制:
          cpus: '1.0'
          内存: 512M

  api:
    图像: mycompany/api:${VERSION}
    重启: unless-stopped
    网络:
      - frontend
      - backend
    环境:
      NODE_ENV: production
      DATABASE_URL: postgresql://postgres:5432/app
      INSTANCE_ID: "{{.Task.Slot}}"
    部署:
      副本: 5
      更新配置:
        并行度: 2
        延迟: 10s
        顺序: start-first
        失败操作: rollback
      回滚配置:
        并行度: 2
        延迟: 10s
      重启策略:
        条件: on-failure
        延迟: 5s
        最大尝试: 3
        窗口: 120s
      资源:
        限制:
          cpus: '1.0'
          内存: 1G
        保留:
          cpus: '0.5'
          内存: 512M
    健康检查:
      测试: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/health"]
      间隔: 30s
      超时: 10s
      重试: 3
      启动期: 60s

  数据库:
    图像: postgres:15-alpine
    重启: unless-stopped
    网络:
      - backend
    环境:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    秘密:
      - db_password
    卷:
      - postgres-data:/var/lib/postgresql/data
    健康检查:
      测试: ["CMD-SHELL", "pg_isready"]
      间隔: 10s
      超时: 5s
      重试: 5
    部署:
      资源:
        限制:
          cpus: '4.0'
          内存: 4G

  数据库副本:
    图像: postgres:15-alpine
    重启: unless-stopped
    网络:
      - backend
    环境:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
      POSTGRES_PRIMARY_HOST: 数据库
      POSTGRES_PRIMARY_PORT: 5432
    秘密:
      - db_password
    卷:
      - postgres-replica-data:/var/lib/postgresql/data
      - ./db/replica-setup.sh:/docker-entrypoint-initdb.d/replica-setup.sh:ro
    依赖:
      数据库:
        条件: service_healthy
    部署:
      资源:
        限制:
          cpus: '2.0'
          内存: 2G

网络:
  frontend:
    驱动: bridge
  backend:
    驱动: bridge
    内部: true

卷:
  postgres-data:
  postgres-replica-data:

秘密:
  db_password:
    文件: ./secrets/db_password.txt

监控和可观察性

生产监控堆栈:

版本: '3.8'

服务:
  prometheus:
    图像: prom/prometheus:latest
    容器名称: prometheus
    重启: unless-stopped
    命令:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=30d'
      - '--web.console.libraries=/usr/share/prometheus/console_libraries'
      - '--web.console.templates=/usr/share/prometheus/consoles'
      - '--web.enable-lifecycle'
    卷:
      - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./monitoring/alerts:/etc/prometheus/alerts:ro
      - prometheus-data:/prometheus
    网络:
      - monitoring
    端口:
      - "9090:9090"
    健康检查:
      测试: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:9090/-/healthy"]
      间隔: 30s
      超时: 10s
      重试: 3
    部署:
      资源:
        限制:
          cpus: '1.0'
          内存: 2G

  grafana:
    图像: grafana/grafana:latest
    容器名称: grafana
    重启: unless-stopped
    环境:
      GF_SECURITY_ADMIN_PASSWORD__FILE: /run/secrets/grafana_password
      GF_INSTALL_PLUGINS: grafana-clock-panel,grafana-simple-json-datasource
      GF_SERVER_ROOT_URL: https://monitoring.example.com
    秘密:
      - grafana_password
    卷:
      - ./monitoring/grafana/provisioning:/etc/grafana/provisioning:ro
      - ./monitoring/grafana/dashboards:/var/lib/grafana/dashboards:ro
      - grafana-data:/var/lib/grafana
    网络:
      - monitoring
      - frontend
    端口:
      - "3001:3000"
    依赖:
      - prometheus
    健康检查:
      测试: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/api/health"]
      间隔: 30s
      超时: 10s
      重试: 3
    部署:
      资源:
        限制:
          cpus: '0.5'
          内存: 512M

  node-exporter:
    图像: prom/node-exporter:latest
    容器名称: node-exporter
    重启: unless-stopped
    命令:
      - '--path.rootfs=/host'
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
    卷:
      - /:/host:ro,rslave
    网络:
      - monitoring
    端口:
      - "9100:9100"
    部署:
      资源:
        限制:
          cpus: '0.2'
          内存: 128M

  cadvisor:
    图像: gcr.io/cadvisor/cadvisor:latest
    容器名称: cadvisor
    重启: unless-stopped
    特权: true
    设备:
      - /dev/kmsg
    卷:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker:/var/lib/docker:ro
      - /dev/disk:/dev/disk:ro
    网络:
      - monitoring
    端口:
      - "8080:8080"
    部署:
      资源:
        限制:
          cpus: '0.3'
          内存: 256M

  loki:
    图像: grafana/loki:latest
    容器名称: loki
    重启: unless-stopped
    命令: -config.file=/etc/loki/local-config.yaml
    卷:
      - ./monitoring/loki-config.yml:/etc/loki/local-config.yaml:ro
      - loki-data:/loki
    网络:
      - monitoring
    端口:
      - "3100:3100"
    部署:
      资源:
        限制:
          cpus: '1.0'
          内存: 1G

  promtail:
    图像: grafana/promtail:latest
    容器名称: promtail
    重启: unless-stopped
    命令: -config.file=/etc/promtail/config.yml
    卷:
      - ./monitoring/promtail-config.yml:/etc/promtail/config.yml:ro
      - /var/log:/var/log:ro
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
    网络:
      - monitoring
    依赖:
      - loki
    部署:
      资源:
        限制:
          cpus: '0.2'
          内存: 256M

网络:
  monitoring:
    驱动: bridge
  frontend:
    驱动: bridge

卷:
  prometheus-data:
  grafana-data:
  loki-data:

秘密:
  grafana_password:
    文件: ./secrets/grafana_password.txt

日志配置

集中式日志设置:

版本: '3.8'

服务:
  应用:
    图像: myapp:latest
    重启: unless-stopped
    日志:
      驱动: "json-file"
      选项:
        最大大小: "10m"
        最大文件: "5"
        标签: "app,environment,version"
        标签: "{{.Name}}/{{.ID}}"
    标签:
      app: "myapp"
      environment: "production"
      version: "${VERSION}"

  nginx:
    图像: nginx:alpine
    重启: unless-stopped
    日志:
      驱动: "syslog"
      选项:
        syslog地址: "tcp://logserver:514"
        标签: "nginx"
        syslog格式: "rfc5424micro"

  api:
    图像: api:latest
    重启: unless-stopped
    日志:
      驱动: "fluentd"
      选项:
        fluentd地址: "localhost:24224"
        标签: "docker.{{.Name}}"
        fluentd异步连接: "true"
        fluentd重试等待: "1s"
        fluentd最大重试: "30"

  数据库:
    图像: postgres:15-alpine
    重启: unless-stopped
    日志:
      驱动: "json-file"
      选项:
        最大大小: "50m"
        最大文件: "10"
        压缩: "true"
    卷:
      - postgres-data:/var/lib/postgresql/data

卷:
  postgres-data:

环境配置管理

多环境设置:

版本: '3.8'

服务:
  应用:
    图像: myapp:${VERSION:-latest}
    重启: unless-stopped
    环境:
      NODE_ENV: ${NODE_ENV:-production}
      LOG_LEVEL: ${LOG_LEVEL:-info}
      PORT: ${APP_PORT:-3000}
      DATABASE_URL: postgresql://${DB_USER}:${DB_PASSWORD}@database:5432/${DB_NAME}
      REDIS_URL: redis://:${REDIS_PASSWORD}@cache:6379
      JWT_SECRET: ${JWT_SECRET}
      API_TIMEOUT: ${API_TIMEOUT:-30000}
      MAX_CONNECTIONS: ${MAX_CONNECTIONS:-100}
    环境文件:
      - .env.${ENVIRONMENT:-production}
      - .env.secrets
    网络:
      - app-network

  数据库:
    图像: postgres:${POSTGRES_VERSION:-15}-alpine
    重启: unless-stopped
    环境:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_INITDB_ARGS: ${POSTGRES_INITDB_ARGS:--E UTF8}
    卷:
      - postgres-data:/var/lib/postgresql/data
    网络:
      - app-network

  缓存:
    图像: redis:${REDIS_VERSION:-7}-alpine
    重启: unless-stopped
    命令: redis-server --requirepass ${REDIS_PASSWORD} --maxmemory ${REDIS_MAX_MEMORY:-256mb}
    卷:
      - redis-data:/data
    网络:
      - app-network

网络:
  app-network:
    驱动: bridge

卷:
  postgres-data:
  redis-data:

健康检查和就绪

全面健康监控:

版本: '3.8'

服务:
  web:
    图像: nginx:alpine
    重启: unless-stopped
    健康检查:
      测试: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"]
      间隔: 30s
      超时: 10s
      重试: 3
      启动期: 40s

  api:
    图像: node:18-alpine
    重启: unless-stopped
    健康检查:
      测试: ["CMD", "node", "healthcheck.js"]
      间隔: 30s
      超时: 10s
      重试: 3
      启动期: 60s
    依赖:
      数据库:
        条件: service_healthy
      缓存:
        条件: service_healthy

  数据库:
    图像: postgres:15-alpine
    重启: unless-stopped
    健康检查:
      测试: ["CMD-SHELL", "pg_isready -U postgres -d production_db || exit 1"]
      间隔: 10s
      超时: 5s
      重试: 5
      启动期: 30s
    卷:
      - postgres-data:/var/lib/postgresql/data

  缓存:
    图像: redis:7-alpine
    重启: unless-stopped
    健康检查:
      测试: ["CMD", "redis-cli", "ping"]
      间隔: 10s
      超时: 5s
      重试: 5
      启动期: 20s
    卷:
      - redis-data:/data

  队列:
    图像: rabbitmq:3-management-alpine
    重启: unless-stopped
    健康检查:
      测试: ["CMD", "rabbitmq-diagnostics", "ping"]
      间隔: 30s
      超时: 10s
      重试: 5
      启动期: 60s
    卷:
      - rabbitmq-data:/var/lib/rabbitmq

卷:
  postgres-data:
  redis-data:
  rabbitmq-data:

备份和恢复

自动备份配置:

版本: '3.8'

服务:
  数据库:
    图像: postgres:15-alpine
    重启: unless-stopped
    环境:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    秘密:
      - db_password
    卷:
      - postgres-data:/var/lib/postgresql/data
    网络:
      - backend

  数据库备份:
    图像: prodrigestivill/postgres-backup-local:15-alpine
    重启: unless-stopped
    环境:
      POSTGRES_HOST: 数据库
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
      SCHEDULE: "@daily"
      BACKUP_KEEP_DAYS: 7
      BACKUP_KEEP_WEEKS: 4
      BACKUP_KEEP_MONTHS: 6
      BACKUP_DIR: /backups
      HEALTHCHECK_PORT: 8080
    秘密:
      - db_password
    卷:
      - ./backups:/backups
      - ./backup-scripts:/scripts:ro
    网络:
      - backend
    依赖:
      数据库:
        条件: service_healthy

  卷备份:
    图像: futurice/docker-volume-backup:2.6.0
    重启: unless-stopped
    环境:
      BACKUP_CRON_EXPRESSION: "0 2 * * *"
      BACKUP_FILENAME: "backup-%Y-%m-%d_%H-%M-%S.tar.gz"
      BACKUP_RETENTION_DAYS: 30
      AWS_S3_BUCKET_NAME: ${S3_BACKUP_BUCKET}
      AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
      AWS_SECRET_ACCESS_KEY_FILE: /run/secrets/aws_secret
    秘密:
      - aws_secret
    卷:
      - postgres-data:/backup/postgres-data:ro
      - redis-data:/backup/redis-data:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./backup-archive:/archive

网络:
  backend:
    驱动: bridge

卷:
  postgres-data:
  redis-data:

秘密:
  db_password:
    文件: ./secrets/db_password.txt
  aws_secret:
    文件: ./secrets/aws_secret.txt

何时使用此技能

使用docker-compose-production当您需要:

  • 将Docker Compose应用程序部署到生产环境
  • 实施安全加固和最佳实践
  • 配置资源限制和保留
  • 设置健康检查和就绪探针
  • 实现具有多个副本的高可用性
  • 配置生产级日志记录和监控
  • 设置自动备份和灾难恢复
  • 管理秘密和敏感配置
  • 实施零停机部署
  • 配置多环境部署策略
  • 设置容器编排以处理生产工作负载
  • 优化性能和资源利用率

最佳实践

  1. 始终使用版本固定:固定特定镜像版本,而不是使用latest,以确保可重复部署。

  2. 实施健康检查:为所有服务配置健康检查,以启用自动恢复和适当的依赖管理。

  3. 设置资源限制:始终定义CPU和内存限制,以防止资源耗尽并确保可预测性能。

  4. 使用秘密管理:永远不要将秘密存储在环境变量或compose文件中;使用Docker秘密或外部秘密管理器。

  5. 配置重启策略:对生产服务使用restart: unless-stopped,以确保从故障中自动恢复。

  6. 实施适当日志记录:配置结构化日志记录与轮换和保留策略,以管理磁盘空间。

  7. 使用只读文件系统:尽可能设置read_only: true,并对临时数据使用tmpfs以提高安全性。

  8. 删除不必要能力:使用cap_drop: ALL并仅添加所需能力,以遵循最小特权原则。

  9. 启用监控:部署监控和可观察性工具,以跟踪应用程序健康和性能指标。

  10. 实施自动备份:配置定期自动备份与保留策略,并测试恢复程序。

  11. 使用内部网络:将后端网络标记为内部,以防止直接外部访问数据库和缓存。

  12. 配置更新策略:定义更新和回滚配置以实现零停机部署。

  13. 实施资源保留:设置资源保留以保障关键服务的最低资源。

  14. 使用多阶段依赖:配置depends_on与健康检查条件,以确保适当的启动顺序。

  15. 文档配置:维护生产配置和部署程序的全面文档。

常见陷阱

  1. 使用最新标签:使用latest或未版本化镜像可能在镜像更新时导致意外行为;始终固定版本。

  2. 忽略资源限制:未设置资源限制可能允许一个服务消耗所有可用资源并导致其他服务崩溃。

  3. 缺失健康检查:没有健康检查,Docker无法确定服务是否实际就绪或需要重启。

  4. 以纯文本存储秘密:将秘密提交到版本控制或存储在环境变量中会暴露敏感数据。

  5. 不测试备份:创建备份而无需定期测试恢复程序会导致实际事件中的数据丢失。

  6. 暴露不必要端口:将所有服务端口发布到主机增加攻击面;仅暴露所需内容。

  7. 以根用户运行:未指定非根用户会使容器容易受到特权升级攻击。

  8. 忽略日志轮换:没有日志轮换,日志可能填满磁盘空间并导致服务或主机崩溃。

  9. 缺失监控:部署没有监控使得在影响用户之前检测和诊断问题变得不可能。

  10. 不使用网络:在默认网络上运行所有服务阻止适当分段并增加安全风险。

  11. 忘记就绪检查:在依赖项就绪之前启动依赖服务会导致连接故障和重启。

  12. 硬编码配置:在compose文件中嵌入环境特定值使得部署到多个环境变得困难。

  13. 忽视安全更新:不定期更新基础镜像会使服务易受已知安全问题影响。

  14. 启动期不足:设置健康检查启动期过短导致在慢速应用程序启动期间出现误报。

  15. 未计划扩展:设计服务时未考虑水平扩展使得处理增加负载变得困难。

资源

官方文档

部署指南

工具和镜像

监控