1. Docker Compose 核心概念解析
Docker Compose 是 Docker 官方提供的容器编排工具,它通过一个 YAML 格式的配置文件来定义和管理多容器应用。与直接使用 Docker 命令相比,Compose 的最大优势在于能够将复杂的容器关系、网络拓扑和存储卷配置声明化,实现"基础设施即代码"。
在实际项目中,我经常遇到需要同时启动多个关联服务的场景。比如一个典型的 Web 应用可能包含前端服务、后端 API、数据库和缓存服务。手动用 docker run 命令逐个启动这些容器不仅繁琐,而且难以维护容器间的依赖关系和网络连接。这正是 Docker Compose 要解决的核心问题。
Compose 配置文件的核心价值体现在三个方面:
- 服务定义:将每个容器抽象为服务(service),明确指定镜像、环境变量、端口映射等参数
- 关系编排:通过 depends_on、links 等字段声明服务间的依赖关系
- 环境隔离:支持通过 profiles 和环境变量实现不同环境(dev/test/prod)的配置切换
提示:虽然 Docker Compose 通常用于开发环境,但在生产环境也可以作为轻量级编排方案,特别是结合 swarm 模式使用时。
2. Compose 文件结构详解
2.1 基础结构剖析
一个完整的 docker-compose.yml 文件通常包含以下顶层配置项:
version: '3.8' # 指定使用的 compose 版本 services: # 服务定义部分 web: image: nginx:alpine ports: - "80:80" db: image: postgres:13 environment: POSTGRES_PASSWORD: example volumes: # 数据卷定义 db-data:version 字段决定了可用的功能特性。我建议至少使用 3.x 版本,因为它支持了更多现代容器特性。不同版本的主要区别在于:
- 2.x:基础服务定义
- 3.x:添加了部署配置、秘密管理等功能
- 3.8+:支持 GPU 资源分配等高级特性
2.2 服务定义关键参数
在 services 部分,每个服务可以配置以下核心参数:
镜像相关:
image: nginx:1.21 # 直接使用公共镜像 build: ./dir # 通过 Dockerfile 构建镜像 context: . dockerfile: Dockerfile.dev网络与端口:
ports: - "8080:80" # 主机端口:容器端口 expose: - "3000" # 仅对其它容器暴露 networks: - frontend - backend环境变量:
environment: NODE_ENV: production DATABASE_URL: postgres://user:pass@db:5432/db env_file: - .env资源限制:
deploy: resources: limits: cpus: '0.50' memory: 512M2.3 网络与存储配置
自定义网络:
networks: frontend: driver: bridge ipam: config: - subnet: 172.28.0.0/16数据卷:
volumes: db-data: # 命名卷 driver: local config: driver: local driver_opts: type: none device: ./config o: bind3. 实战配置案例
3.1 Web 应用全栈配置
下面是一个典型的 LAMP 应用配置示例:
version: '3.8' services: web: image: php:8.1-apache ports: - "8000:80" volumes: - ./src:/var/www/html depends_on: - db environment: DB_HOST: db db: image: mariadb:10.6 volumes: - db_data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: app MYSQL_USER: user MYSQL_PASSWORD: password phpmyadmin: image: phpmyadmin ports: - "8080:80" depends_on: - db environment: PMA_HOST: db volumes: db_data:这个配置展示了几个关键实践:
- 使用 depends_on 确保数据库先启动
- 通过 volumes 实现代码热更新(开发时特别有用)
- 环境变量隔离敏感信息
- 命名卷持久化数据库
3.2 微服务架构配置
对于更复杂的微服务场景,配置可能如下:
version: '3.8' services: gateway: build: ./gateway ports: - "80:8080" networks: - public - private user-service: build: ./services/user networks: - private environment: DB_URL: "postgres://user:pass@user-db:5432/users" order-service: build: ./services/order networks: - private user-db: image: postgres:13 volumes: - user-data:/var/lib/postgresql/data networks: - private environment: POSTGRES_PASSWORD: pass networks: public: private: internal: true volumes: user-data:这个配置的关键点:
- 使用 internal 网络隔离数据库等敏感服务
- 多网络实现服务分层
- 每个服务独立构建上下文
4. 高级配置技巧
4.1 多环境配置管理
我通常使用扩展字段(extension fields)实现多环境配置:
version: '3.8' x-env: &default-env DB_HOST: db DB_PORT: 5432 services: web: image: app environment: <<: *default-env NODE_ENV: development web-prod: image: app environment: <<: *default-env NODE_ENV: production另一种方式是使用多个 compose 文件:
# base.yml - 通用配置 # dev.yml - 开发环境覆盖配置 docker-compose -f base.yml -f dev.yml up4.2 健康检查与依赖管理
services: web: depends_on: db: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 30s timeout: 10s retries: 3 db: healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 2s retries: 104.3 资源限制与部署策略
services: worker: deploy: resources: limits: cpus: '0.50' memory: 512M restart_policy: condition: on-failure delay: 5s max_attempts: 3 update_config: parallelism: 2 delay: 10s5. 常见问题排查
5.1 端口冲突问题
当遇到端口已被占用错误时,可以:
- 检查主机端口使用情况:
netstat -tuln | grep <port> - 修改 compose 文件中的端口映射
- 使用动态端口:
ports: - "3000"(不绑定主机端口)
5.2 容器启动顺序问题
虽然 depends_on 可以控制启动顺序,但不能确保服务就绪。解决方案:
- 实现健康检查(如 4.2 节所示)
- 在应用代码中添加重试逻辑
- 使用 wait-for-it.sh 等工具脚本
5.3 环境变量注入失败
常见原因和解决方法:
- .env 文件未放在 compose 文件同级目录
- 变量名包含特殊字符(应使用 A-Z, 0-9, _)
- 在 build 阶段需要变量:使用 ARG 指令
6. 性能优化实践
6.1 构建缓存优化
services: app: build: context: . cache_from: - myapp:latest image: myapp:latest6.2 卷性能调优
对于高IO应用,可以配置 volume 驱动选项:
volumes: data: driver_opts: type: tmpfs device: tmpfs6.3 并发控制
services: worker: deploy: replicas: 4 update_config: parallelism: 2 failure_action: rollback7. 安全最佳实践
7.1 最小权限原则
services: db: user: postgres read_only: true7.2 秘密管理
services: app: secrets: - db_password secrets: db_password: file: ./secrets/db_password.txt7.3 网络隔离
networks: internal: internal: true public: driver: bridge8. 实际项目经验分享
在最近的一个电商项目中,我们使用 Compose 管理了超过 15 个微服务。几个关键经验:
- 配置模块化:将通用配置提取到 base.yml,各环境通过 override 文件定制
- 本地开发优化:
- 使用 bind mount 实现代码热加载
- 为每个开发者分配独立的端口范围
- CI/CD 集成:
docker-compose -f docker-compose.ci.yml build docker-compose -f docker-compose.ci.yml up -d - 调试技巧:
docker-compose logs -f实时查看日志docker-compose exec service sh进入容器调试
一个特别有用的模式是为每个服务添加一个 debug 配置:
services: app: # 正常配置 app-debug: extends: app environment: DEBUG: "true" ports: - "9229:9229" # Node.js 调试端口