Docker Compose黄金模板:5套实战配置与避坑指南

1. 为什么需要Docker Compose模板?

在容器化部署的实践中,我发现大多数开发者都会遇到一个共同痛点:每次启动新项目时,都要从头开始编写docker-compose.yml文件。这不仅浪费时间,还容易因为配置不规范导致各种运行时错误。经过三年多的容器化部署实践,我整理出了这套覆盖90%场景的标准化模板。

Docker Compose作为定义和运行多容器应用的工具,其配置文件的质量直接决定了部署的稳定性和可维护性。一个典型的反例是:某次我在紧急部署时手写了一个compose文件,结果因为缩进错误导致服务无法启动,排查了两小时才发现是YAML格式问题。这种低级错误完全可以通过标准化模板避免。

2. 5套黄金模板详解

2.1 基础Web服务模板(Nginx+PHP/Python)

version: '3.8' services: web: image: nginx:alpine ports: - "80:80" volumes: - ./html:/usr/share/nginx/html - ./nginx.conf:/etc/nginx/conf.d/default.conf depends_on: - app networks: - backend app: build: . environment: - DB_HOST=db - DB_USER=root volumes: - ./app:/app networks: - backend healthcheck: test: ["CMD", "curl", "-f", "http://localhost:5000"] interval: 30s timeout: 10s retries: 3 networks: backend: driver: bridge

关键设计点:

  1. 使用alpine基础镜像减小体积
  2. 通过volumes实现代码热更新
  3. healthcheck确保服务可用性
  4. 独立网络隔离环境

实测中常见问题:

  • Nginx配置需要预先挂载
  • 健康检查端点要与应用实际端口一致
  • 开发环境建议添加restart: unless-stopped

2.2 数据库集群模板(MySQL主从+Redis)

version: '3.8' services: mysql-master: image: mysql:8.0 environment: - MYSQL_ROOT_PASSWORD=rootpass - MYSQL_REPLICATION_USER=repl - MYSQL_REPLICATION_PASSWORD=replpass ports: - "3306:3306" volumes: - mysql-master-data:/var/lib/mysql command: - --server-id=1 - --log-bin=mysql-bin - --binlog-format=ROW - --gtid-mode=ON - --enforce-gtid-consistency=ON mysql-slave: image: mysql:8.0 environment: - MYSQL_ROOT_PASSWORD=rootpass depends_on: - mysql-master volumes: - mysql-slave-data:/var/lib/mysql command: - --server-id=2 - --log-bin=mysql-bin - --binlog-format=ROW - --gtid-mode=ON - --enforce-gtid-consistency=ON - --skip-slave-start - --relay-log=mysql-relay-bin redis: image: redis:alpine ports: - "6379:6379" volumes: - redis-data:/data command: redis-server --appendonly yes volumes: mysql-master-data: mysql-slave-data: redis-data:

避坑经验:

  1. MySQL主从需要server-id唯一
  2. 生产环境务必设置volume持久化
  3. Redis启用AOF持久化
  4. 首次启动后需手动配置主从关系

2.3 微服务模板(Spring Cloud+Gateway)

version: '3.8' services: config-server: image: springcloud/config-server ports: - "8888:8888" environment: - SPRING_PROFILES_ACTIVE=native volumes: - ./config:/config gateway: image: springcloud/gateway ports: - "8080:8080" depends_on: - config-server environment: - SPRING_CLOUD_CONFIG_URI=http://config-server:8888 service-a: image: your-service-a depends_on: - config-server environment: - SPRING_CLOUD_CONFIG_URI=http://config-server:8888 service-b: image: your-service-b depends_on: - config-server environment: - SPRING_CLOUD_CONFIG_URI=http://config-server:8888 zipkin: image: openzipkin/zipkin ports: - "9411:9411"

关键配置:

  1. 统一配置中心先行启动
  2. 服务间通过服务名通信
  3. 链路追踪独立部署
  4. 建议添加deploy.replicas实现高可用

2.4 机器学习训练环境模板

version: '3.8' services: jupyter: image: tensorflow/tensorflow:latest-gpu-jupyter ports: - "8888:8888" volumes: - ./notebooks:/tf/notebooks - ./data:/data deploy: resources: reservations: devices: - driver: nvidia count: 1 capabilities: [gpu] environment: - NVIDIA_VISIBLE_DEVICES=all mlflow: image: mlflow/mlflow ports: - "5000:5000" volumes: - ./mlruns:/mlruns command: - "mlflow" - "server" - "--host" - "0.0.0.0" postgres: image: postgres:13 environment: - POSTGRES_PASSWORD=mlflow - POSTGRES_USER=mlflow - POSTGRES_DB=mlflow volumes: - pg-data:/var/lib/postgresql/data volumes: pg-data:

GPU使用要点:

  1. 需要NVIDIA Container Toolkit
  2. 显存资源需要显式声明
  3. 数据卷挂载路径避免权限问题
  4. MLflow需配置数据库后端

2.5 监控告警全家桶模板

version: '3.8' services: prometheus: image: prom/prometheus ports: - "9090:9090" volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml command: - '--config.file=/etc/prometheus/prometheus.yml' grafana: image: grafana/grafana ports: - "3000:3000" volumes: - grafana-data:/var/lib/grafana depends_on: - prometheus alertmanager: image: prom/alertmanager ports: - "9093:9093" volumes: - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml node-exporter: image: prom/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.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)' volumes: grafana-data:

监控系统注意事项:

  1. Prometheus配置需预先准备
  2. Grafana数据源需手动配置
  3. 生产环境建议添加认证
  4. 告警规则需要定期维护

3. 避坑指南:那些年我踩过的坑

3.1 环境变量管理的最佳实践

新手常犯的错误是直接在compose文件硬编码敏感信息。正确的做法是:

services: db: image: mysql env_file: - .env.db environment: - TZ=${TIMEZONE}

配套的.env.db文件:

MYSQL_ROOT_PASSWORD=complex_password MYSQL_DATABASE=app_db

经验总结:

  1. 敏感信息必须通过env_file管理
  2. 通用配置可使用环境变量传参
  3. 不同环境使用不同env文件
  4. 禁止将.env提交到版本控制

3.2 健康检查的合理配置

我曾遇到服务"假死"的情况——容器在运行但应用已崩溃。有效的健康检查应这样配置:

healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1"] interval: 30s timeout: 5s retries: 3 start_period: 40s

关键参数说明:

  • interval:检查间隔不要小于30秒
  • timeout:根据接口响应时间调整
  • start_period:给应用留出启动时间
  • retries:避免偶发失败导致误判

3.3 网络配置的进阶技巧

当需要连接多个compose项目时,可以创建外部网络:

docker network create shared-network

然后在各compose文件中:

networks: default: external: name: shared-network

常见问题解决方案:

  1. 服务发现用服务名而非IP
  2. 跨项目通信需要相同网络
  3. 避免使用默认的bridge网络
  4. 生产环境建议配置网络别名

4. 模板的定制与扩展

4.1 多文件组合技巧

大型项目建议拆分配置:

docker-compose.yml # 基础配置 docker-compose.override.yml # 开发环境扩展 docker-compose.prod.yml # 生产环境配置

启动时指定文件:

docker-compose -f docker-compose.yml -f docker-compose.prod.yml up

4.2 参数化模板设计

通过环境变量实现配置动态化:

services: app: image: ${APP_IMAGE:-default-image} ports: - "${HOST_PORT}:${CONTAINER_PORT}"

配套的.env文件:

APP_IMAGE=your-registry/app:v1.2 HOST_PORT=8080 CONTAINER_PORT=80

4.3 版本控制策略

推荐的文件结构:

project/ ├── docker/ │ ├── templates/ # 标准模板库 │ ├── environments/ # 各环境配置 │ └── scripts/ # 部署脚本 ├── .env.example # 环境变量示例 └── docker-compose.yml # 主入口文件

版本管理要点:

  1. 模板与项目代码分离
  2. 环境配置按分支管理
  3. 重要变更记录CHANGELOG
  4. 定期同步模板更新

5. 实战案例:电商系统部署

5.1 架构设计

典型电商栈组合:

  • 前端:Nginx + Vue.js
  • 后端:Spring Boot + MySQL + Redis
  • 辅助:Elasticsearch + RabbitMQ

5.2 完整compose配置

version: '3.8' services: nginx: image: nginx:alpine ports: - "80:80" - "443:443" volumes: - ./frontend/dist:/usr/share/nginx/html - ./nginx/conf.d:/etc/nginx/conf.d - ./nginx/certs:/etc/nginx/certs depends_on: - gateway gateway: build: ./gateway ports: - "8080:8080" environment: - SPRING_PROFILES_ACTIVE=docker depends_on: - product-service - order-service - user-service product-service: build: ./services/product environment: - DB_HOST=mysql - REDIS_HOST=redis depends_on: - mysql - redis mysql: image: mysql:8.0 environment: - MYSQL_ROOT_PASSWORD=root - MYSQL_DATABASE=ecommerce volumes: - mysql-data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] timeout: 20s retries: 10 redis: image: redis:alpine ports: - "6379:6379" volumes: - redis-data:/data volumes: mysql-data: redis-data:

5.3 部署流程

  1. 准备环境变量
cp .env.example .env # 编辑实际配置
  1. 构建并启动
docker-compose build docker-compose up -d
  1. 验证服务
docker-compose ps curl http://localhost/health
  1. 生产环境扩展
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d