1. Docker Compose 是什么?为什么你需要它
如果你已经接触过 Docker,肯定体验过它"一次构建,到处运行"的便利性。但真实生产环境中,我们很少只运行单个容器——一个典型的 Web 应用就需要数据库、缓存、后端服务等多个容器协同工作。这时候 Docker Compose 就派上用场了。
简单来说,Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。它通过一个 YAML 文件(通常命名为 docker-compose.yml)来配置所有服务,然后只需一条命令就能启动整个应用栈。我刚开始接触容器编排时,手动用 docker run 启动每个容器,不仅命令冗长,容器间的网络连接和依赖关系更是噩梦。Compose 把这些都标准化了,让开发效率提升了一个数量级。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心概念与工作原理
2.1 核心三要素
-
服务(Service):一个服务对应一个容器,比如一个 MySQL 数据库容器或 Node.js 应用容器。在 Compose 文件中,每个服务定义了容器如何运行,包括镜像、环境变量、端口映射等。
-
项目(Project):由一组关联服务组成的完整应用。Compose 会为每个项目创建独立的网络,确保服务间可以通信同时隔离不同项目。
-
Compose 文件:YAML 格式的配置文件,定义服务、网络和卷。这是 Compose 的核心,我建议每个项目都将其纳入版本控制。
2.2 底层实现原理
当执行 docker-compose up 时:
- 解析 YAML 文件并创建项目网络
- 为每个服务创建容器(相当于 docker run)
- 自动处理服务依赖关系(比如先启动数据库再启动应用)
- 收集所有容器的日志统一输出
提示:Compose 其实是对 Docker API 的高级封装,最终还是会调用 Docker 引擎完成实际工作。你可以用
docker-compose config查看 Compose 生成的完整配置。
3. 从零编写你的第一个 Compose 文件
3.1 基础结构示例
下面是一个典型的 docker-compose.yml 文件结构:
yaml复制version: '3.8' # 指定使用的 Compose 版本
services:
web: # 服务名称
image: nginx:alpine # 使用的镜像
ports:
- "80:80" # 端口映射
volumes:
- ./html:/usr/share/nginx/html # 挂载本地目录
db:
image: postgres:13
environment:
POSTGRES_PASSWORD: example
3.2 关键配置项详解
-
版本选择:
- 建议使用 3.x 版本(最新为 3.8)
- 不同版本支持的功能有差异,新版本支持更多部署选项
-
服务依赖:
yaml复制depends_on: - db - redis这确保服务按顺序启动,但注意:这仅控制启动顺序,不保证服务已准备好接收连接
-
环境变量管理:
- 直接定义:
yaml复制environment: DB_HOST: db - 使用.env文件:
bash复制然后在 Compose 中引用:# .env 文件 DB_PASSWORD=secretyaml复制environment: DB_PASSWORD: ${DB_PASSWORD}
- 直接定义:
4. 生产环境最佳实践
4.1 资源限制与重启策略
yaml复制services:
app:
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
restart: unless-stopped # 自动重启除非明确停止
4.2 多环境配置方案
我推荐使用扩展字段(extension fields)实现环境差异:
yaml复制x-common: &common
image: myapp
environment:
- LOG_LEVEL=info
services:
web:
<<: *common
environment:
- ENV=development
web-prod:
<<: *common
environment:
- ENV=production
4.3 健康检查配置
yaml复制healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
5. 高级技巧与疑难排查
5.1 性能优化技巧
-
并行启动:Compose 默认并行启动服务,对于大量服务可以控制并行度:
bash复制
docker-compose up --parallel 5 -
构建缓存:在 CI/CD 流水线中,可以复用构建缓存:
bash复制
docker-compose build --pull --no-cache
5.2 常见问题排查
问题1:端口冲突
- 现象:
Bind for 0.0.0.0:80 failed: port is already allocated - 解决:
bash复制# 查找占用进程 sudo lsof -i :80 # 或者停止所有容器 docker-compose down
问题2:服务启动顺序问题
- 现象:应用启动时数据库还未准备好
- 解决方案:在应用中添加重试逻辑,或使用 wait-for-it.sh 脚本:
yaml复制command: ["./wait-for-it.sh", "db:5432", "--", "npm", "start"]
6. 实际项目案例解析
6.1 全栈应用配置示例
yaml复制version: '3.8'
services:
frontend:
build: ./frontend
ports:
- "3000:3000"
volumes:
- ./frontend:/app
- /app/node_modules
backend:
build: ./backend
ports:
- "5000:5000"
environment:
- DB_HOST=db
depends_on:
- db
db:
image: postgres:13
volumes:
- db_data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: password
volumes:
db_data:
6.2 CI/CD 集成方案
在 GitLab CI 中使用 Compose 的示例:
yaml复制test:
stage: test
script:
- docker-compose -f docker-compose.test.yml up -d
- docker-compose -f docker-compose.test.yml exec -T app npm test
- docker-compose -f docker-compose.test.yml down
7. 版本迁移与升级指南
从 Compose v2 升级到 v3 需要注意:
-
网络变化:
- v2 默认创建名为
projectname_default的网络 - v3 使用
projectname_default但配置方式不同
- v2 默认创建名为
-
废弃配置:
yaml复制# v2 中的 links 在 v3 中已废弃 links: - db应该使用网络别名替代:
yaml复制networks: default: aliases: - database -
扩展字段:v3 引入了更灵活的扩展字段(x-*)
8. 安全加固建议
-
最小权限原则:
yaml复制services: app: user: "1000:1000" # 使用非root用户 read_only: true # 只读文件系统 -
秘密管理:
yaml复制secrets: db_password: file: ./db_password.txt services: db: secrets: - db_password -
网络隔离:
yaml复制networks: frontend: backend: internal: true # 禁止外部访问
9. 监控与日志管理
9.1 集中式日志配置
yaml复制services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
9.2 指标监控集成
yaml复制monitoring:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
10. 替代方案比较
虽然 Docker Compose 非常流行,但在某些场景下可能需要考虑其他工具:
| 工具 | 适用场景 | 学习曲线 | 集群支持 |
|---|---|---|---|
| Docker Compose | 本地开发、单机部署 | 低 | 否 |
| Kubernetes | 生产集群部署 | 高 | 是 |
| Nomad | 简单轻量级编排 | 中 | 是 |
| Podman Compose | 无守护进程环境 | 低 | 否 |
对于大多数开发场景,Docker Compose 仍然是简单性和功能性平衡的最佳选择。我在处理需要快速原型验证的项目时,90% 的情况都会首选 Compose。只有当应用需要扩展到多节点集群时,才会考虑 Kubernetes 等更复杂的方案。
