🎼 Docker Compose 编排
🤔 什么是 Docker Compose
Docker Compose 是一个多容器编排工具,通过一个 compose.yml(旧版为 docker-compose.yml)文件定义和运行多容器 Docker 应用。
核心价值:一条命令启动整个应用栈(Web + Database + Redis + ...)
传统方式 vs Compose 方式
# ❌ 传统方式:手动启动每个容器
docker run -d --name db -e POSTGRES_PASSWORD=secret postgres:16-alpine
docker run -d --name redis redis:7-alpine
docker run -d --name web --link db --link redis -p 3000:3000 myapp:latest
# ✅ Compose 方式:一条命令
docker compose up -d
📄 compose.yml 文件结构
compose.yml 基本结构
version: '3.9' # 可选,Compose v2 已不强制要求
services: # 定义容器服务
web:
build: .
ports:
- '3000:3000'
volumes: # 定义数据卷
db_data:
networks: # 定义网络
app_net:
顶级配置项
| 配置项 | 说明 | 必需 |
|---|---|---|
services | 定义容器服务(最核心) | ✅ 必需 |
volumes | 定义命名数据卷 | ❌ 可选 |
networks | 定义自定义网络 | ❌ 可选 |
configs | 定义配置文件(Swarm 模式) | ❌ 可选 |
secrets | 定义密钥(Swarm 模式) | ❌ 可选 |
🏗️ Services 配置详解
services 是 compose.yml 中最核心的部分,每个 service 对应一个容器。
web 服务完整配置示例
services:
web:
# 镜像来源
image: myapp:latest
build:
context: .
dockerfile: Dockerfile
args:
NODE_ENV: production
# 容器命名
container_name: myapp-web
# 重启策略
restart: unless-stopped
# 端口映射
ports:
- '3000:3000'
- '9229:9229' # Node.js 调试端口
# 环境变量
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
env_file:
- .env
# 卷挂载
volumes:
- ./data:/app/data:ro
- app_logs:/app/logs
# 网络
networks:
- app_net
# 依赖关系
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
# 健康检查
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:3000/health']
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# 资源限制(Compose v2)
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
常用 Services 配置项速查
| 配置项 | 说明 | 示例 |
|---|---|---|
image | 使用的镜像 | image: postgres:16-alpine |
build | 构建配置 | build: . 或 build: { context: ., dockerfile: Dockerfile } |
ports | 端口映射 | ports: ["3000:3000", "9229:9229"] |
environment | 环境变量 | environment: ["NODE_ENV=production"] |
env_file | 环境变量文件 | env_file: [.env, .env.prod] |
volumes | 卷挂载 | volumes: ["./data:/app/data"] |
networks | 加入的网络 | networks: ["app_net"] |
depends_on | 依赖服务 | depends_on: [db, redis] |
restart | 重启策略 | restart: unless-stopped |
healthcheck | 健康检查 | 见上例 |
command | 覆盖默认命令 | command: npm run dev |
entrypoint | 覆盖默认入口点 | entrypoint: ["/entrypoint.sh"] |
🌟 真实案例:Web + PostgreSQL + Redis
以下是一个典型的全栈应用 Compose 配置:
compose.yml — 完整生产级配置
services:
# ─── Web 应用 ────────────────────────────────
web:
build:
context: .
dockerfile: Dockerfile
container_name: myapp-web
restart: unless-stopped
ports:
- '3000:3000'
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://postgres:secret@db:5432/myapp
- REDIS_URL=redis://redis:6379
env_file:
- .env.production
volumes:
- ./uploads:/app/uploads:ro
networks:
- app_net
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:3000/health']
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# ─── PostgreSQL 数据库 ────────────────────────
db:
image: postgres:16-alpine
container_name: myapp-db
restart: unless-stopped
ports:
- '5432:5432'
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp
volumes:
- db_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- app_net
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U postgres']
interval: 10s
timeout: 5s
retries: 5
# ─── Redis 缓存 ──────────────────────────────
redis:
image: redis:7-alpine
container_name: myapp-redis
restart: unless-stopped
ports:
- '6379:6379'
command: redis-server --appendonly yes --requirepass secret
volumes:
- redis_data:/data
networks:
- app_net
healthcheck:
test: ['CMD', 'redis-cli', '-a', 'secret', 'ping']
interval: 10s
timeout: 5s
retries: 5
# ─── Nginx 反向代理 ──────────────────────────
nginx:
image: nginx:alpine
container_name: myapp-nginx
restart: unless-stopped
ports:
- '80:80'
- '443:443'
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
networks:
- app_net
depends_on:
- web
networks:
app_net:
driver: bridge
volumes:
db_data:
redis_data:
配套 .env 文件
# 数据库配置
POSTGRES_USER=postgres
POSTGRES_PASSWORD=mysecretpassword
POSTGRES_DB=myapp
# Redis 配置
REDIS_PASSWORD=mysecretpassword
# 应用配置
NODE_ENV=production
PORT=3000
:::tip 关于 .env 文件
- Compose 会自动加载同级目录的
.env文件 - 变量使用
${VARIABLE}或$VARIABLE引用 - 敏感信息应使用
secrets或运行时挂载,不应提交到 Git
:::
🔧 Docker Compose 常用命令
docker compose up — 启动服务
# 启动所有服务(前台运行,Ctrl+C 停止)
docker compose up
# 后台启动所有服务
docker compose up -d
# 重新构建后启动(代码变更后)
docker compose up -d --build
# 启动指定服务
docker compose up -d web
# 强制重新创建容器(即使配置未变)
docker compose up -d --force-recreate
docker compose down — 停止并删除
# 停止并删除容器、网络
docker compose down
# 同时删除命名卷
docker compose down -v
# 同时删除镜像(删除所有服务使用的镜像)
docker compose down --rmi all
# 停止但不删除 volumes
docker compose down --volumes # 删除 volumes
docker compose logs — 查看日志
# 查看所有服务日志
docker compose logs
# 实时跟踪日志(类似 tail -f)
docker compose logs -f
# 查看指定服务日志
docker compose logs web
# 显示最后 100 行
docker compose logs --tail=100 web
# 带时间戳
docker compose logs -t web
docker compose ps — 查看服务状态
# 查看运行中的服务
docker compose ps
# 查看所有服务(含已停止)
docker compose ps -a
docker compose exec — 进入容器
# 在运行中的容器中执行命令
docker compose exec web bash
# 以 root 用户进入
docker compose exec -u root web bash
# 执行单条命令
docker compose exec web npm run db:migrate
docker compose build — 构建镜像
# 构建所有服务镜像
docker compose build
# 构建指定服务
docker compose build web
# 不使用缓存重新构建
docker compose build --no-cache
# 并行构建(加速)
docker compose build --parallel
docker compose restart — 重启服务
# 重启所有服务
docker compose restart
# 重启指定服务
docker compose restart web
命令速查表
| 命令 | 作用 | 常用参数 |
|---|---|---|
docker compose up -d | 后台启动所有服务 | --build 重新构建 |
docker compose down | 停止并删除容器网络 | -v 删除卷,--rmi all 删除镜像 |
docker compose ps | 查看服务状态 | -a 显示已停止 |
docker compose logs -f | 实时查看日志 | --tail=100 最后100行 |
docker compose exec web sh | 进入容器 | -u root 以 root 进入 |
docker compose build | 构建镜像 | --no-cache 无缓存 |
docker compose restart web | 重启服务 | 无 |
docker compose stop | 停止服务(不删除) | 无 |
docker compose start | 启动已停止的服务 | 无 |
docker compose pull | 拉取最新镜像 | --ignore-pull-failures |
docker compose config | 验证并显示配置 | --services 显示服务名 |
docker compose top | 显示运行进程 | 无 |
🔐 环境变量与 .env 文件
Compose 支持多种方式管理环境变量:
1. 直接在 compose.yml 中定义
services:
web:
environment:
- NODE_ENV=production
- API_KEY=secret-key
2. 使用 .env 文件(推荐)
compose.yml
services:
web:
image: myapp:latest
environment:
- NODE_ENV=${NODE_ENV:-production}
- API_PORT=${API_PORT:-3000}
NODE_ENV=production
API_PORT=3000
DATABASE_URL=postgresql://postgres:secret@localhost:5432/myapp
3. 使用 env_file 指定文件
services:
web:
env_file:
- .env.production
- .env.secrets
:::warning .env 文件安全注意事项
- 不要提交
.env到 Git:在.gitignore中添加.env* - 提供
.env.example:列出所需变量但不填写真实值 - 生产环境:使用 CI/CD 注入或密钥管理服务
:::
# .env.example — 复制为 .env 并填入真实值
NODE_ENV=development
API_PORT=3000
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
REDIS_URL=redis://localhost:6379
JWT_SECRET=your-jwt-secret-here
⚖️ Docker Compose vs Kubernetes:如何选择
| 维度 | Docker Compose | Kubernetes |
|---|---|---|
| 复杂度 | 简单,YAML 直观 | 复杂,学习曲线陡峭 |
| 适用场景 | 本地开发、小型部署 | 生产环境、大规模集群 |
| 健康检查 | 支持(healthcheck) | 支持(liveness/readiness) |
| 自动扩缩容 | ❌ 不支持 | ✅ 支持(HPA) |
| 滚动更新 | ❌ 不支持 | ✅ 支持 |
| 服务发现 | Docker DNS | CoreDNS + Service |
| 存储 | 本地卷、绑定挂载 | PV/PVC、CSI |
| 网络 | Docker 网络 | CNI 插件(Calico/Flannel) |
| 资源限制 | 支持(v2) | 完善(CPU/Memory/Storage) |
| 监控 | 需外接 | 内置 Metrics Server |
决策树
我需要编排多容器应用
├── 本地开发 / CI 测试
│ └── ✅ 使用 Docker Compose
├── 小型生产部署(< 5 节点)
│ ├── 团队无 K8s 经验 → ✅ Docker Compose + 手动管理
│ └── 团队有 K8s 经验 → ⚠️ 可考虑 K8s
└── 中大型生产部署(≥ 5 节点)/ 高可用需求
└── ✅ 使用 Kubernetes
:::tip 混合使用策略
许多团队采用混合策略:
- 开发环境:Docker Compose(快速、简单)
- 生产环境:Kubernetes(可扩展、高可用)
可以使用 kompose 工具将 Compose 文件转换为 K8s 配置:
kompose convert -f compose.yml -o k8s/
:::
🚀 Compose 高级特性
Profile — 环境配置
compose.yml with profiles
services:
web:
image: myapp:latest
profiles:
- web
db:
image: postgres:16-alpine
profiles:
- db
redis:
image: redis:7-alpine
profiles:
- cache
# 仅开发环境启用的服务
adminer:
image: adminer:latest
ports:
- '8080:8080'
profiles:
- dev
使用 profile 启动
# 默认启动(所有服务)
docker compose up -d
# 仅启动 web 和 db profile 的服务
docker compose --profile web --profile db up -d
# 启动 dev profile(包含 adminer)
docker compose --profile dev up -d
extends — 配置复用
compose.base.yml — 基础配置
services:
app:
image: myapp:latest
environment:
- NODE_ENV=production
restart: unless-stopped
compose.yml — 继承基础配置
services:
web:
extends:
file: compose.base.yml
service: app
ports:
- '3000:3000'
depends_on:
- db
worker:
extends:
file: compose.base.yml
service: app
command: npm run worker
📋 Compose 最佳实践
1. 使用命名卷而非绑定挂载(生产环境)
❌ 开发环境可用,生产不推荐
volumes:
- ./data:/app/data # 绑定挂载:依赖宿主机路径
✅ 生产推荐:命名卷
volumes:
db_data: # 命名卷:Docker 管理,可迁移
services:
db:
volumes:
- db_data:/var/lib/postgresql/data
2. 设置重启策略
重启策略选择
services:
web:
# always:始终重启(包括手动停止后 daemon 重启)
restart: always
worker:
# unless-stopped:除非手动停止,否则始终重启(推荐)
restart: unless-stopped
batch:
# no:不重启(批量任务)
restart: 'no'
debug:
# on-failure:失败时重启
restart: on-failure:5 # 最多重启 5 次
3. 使用 healthcheck 控制启动顺序
使用 healthcheck 而非 wait-for-it 脚本
services:
db:
image: postgres:16-alpine
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U postgres']
interval: 10s
timeout: 5s
retries: 5
web:
image: myapp:latest
depends_on:
db:
condition: service_healthy # 等待 db 健康后才启动
4. 资源限制
Compose v2 资源限制
services:
web:
deploy:
resources:
limits:
cpus: '1.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M
🔗 下一步
- 🌐 网络与存储 — 理解 Docker 网络与数据持久化
- 🏗️ 生产级最佳实践 — 镜像优化、多架构、CI/CD 集成