Docker 完全指南 / 10 - Compose 进阶
10 - Compose 进阶
多环境配置、Profiles、扩展字段、Compose Watch 等高级特性。
10.1 多环境配置策略
方案一:多配置文件覆盖
项目结构:
compose.yaml ← 基础配置
compose.override.yaml ← 开发环境覆盖(自动加载)
compose.prod.yaml ← 生产环境覆盖(手动指定)
compose.test.yaml ← 测试环境覆盖
compose.yaml — 基础配置:
services:
app:
build: ./app
environment:
- NODE_ENV=production
- DB_HOST=db
depends_on:
- db
db:
image: postgres:16
volumes:
- pg-data:/var/lib/postgresql/data
volumes:
pg-data:
compose.override.yaml — 开发环境(自动加载):
services:
app:
build:
target: development
ports:
- "3000:3000"
- "9229:9229" # Node.js 调试端口
volumes:
- ./app/src:/app/src # 热重载
environment:
- DEBUG=app:*
db:
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=devpassword
- POSTGRES_DB=myapp_dev
compose.prod.yaml — 生产环境:
services:
app:
build:
target: production
ports:
- "80:3000"
restart: unless-stopped
deploy:
resources:
limits:
cpus: "2.0"
memory: 1G
db:
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
file: ./secrets/db_password.txt
使用方式
# 开发环境(自动加载 compose.yaml + compose.override.yaml)
docker compose up -d
# 生产环境
docker compose -f compose.yaml -f compose.prod.yaml up -d
# 或使用简写(注意顺序:基础 → 覆盖)
docker compose -f compose.yaml -f compose.prod.yaml config > final.yaml
方案二:环境变量替换
# compose.yaml
services:
app:
image: my-app:${APP_VERSION:-latest}
ports:
- "${APP_PORT:-3000}:3000"
environment:
- NODE_ENV=${NODE_ENV:-development}
- LOG_LEVEL=${LOG_LEVEL:-debug}
deploy:
resources:
limits:
memory: ${MEMORY_LIMIT:-512m}
# .env.development
APP_VERSION=latest
APP_PORT=3000
NODE_ENV=development
LOG_LEVEL=debug
MEMORY_LIMIT=512m
# .env.production
APP_VERSION=1.0.0
APP_PORT=80
NODE_ENV=production
LOG_LEVEL=warn
MEMORY_LIMIT=1G
# 使用环境文件
docker compose --env-file .env.development up -d
docker compose --env-file .env.production up -d
10.2 Profiles(配置文件组)
Profiles 允许按需启动特定服务组,适合开发工具、调试服务等可选组件。
services:
# 核心服务(始终启动)
app:
build: ./app
ports:
- "8080:3000"
profiles: [] # 空 = 始终启动
db:
image: postgres:16
profiles: []
redis:
image: redis:7-alpine
profiles: []
# 开发工具(仅在 dev profile 下启动)
adminer:
image: adminer
ports:
- "8081:8080"
profiles:
- dev
mailhog:
image: mailhog/mailhog
ports:
- "1025:1025"
- "8025:8025"
profiles:
- dev
- test
# 测试服务
test-db:
image: postgres:16
environment:
POSTGRES_DB: test
profiles:
- test
# 监控服务
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
profiles:
- monitoring
grafana:
image: grafana/grafana
ports:
- "3000:3000"
profiles:
- monitoring
# 仅启动核心服务(无 profile)
docker compose up -d
# 启动核心 + 开发工具
docker compose --profile dev up -d
# 启动核心 + 测试服务
docker compose --profile test up -d
# 启动核心 + 监控
docker compose --profile monitoring up -d
# 启动多个 profile
docker compose --profile dev --profile monitoring up -d
# 通过环境变量启用 profiles
COMPOSE_PROFILES=dev docker compose up -d
10.3 扩展字段(Extension Fields)
使用 YAML 锚点(Anchors)和引用(Aliases)实现配置复用。
基本用法
# 使用 x- 前缀定义扩展字段(Compose 会忽略这些字段)
x-common-env: &common-env
TZ: Asia/Shanghai
LANG: C.UTF-8
x-logging: &default-logging
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
services:
app:
image: my-app:latest
environment:
<<: *common-env
APP_ENV: production
<<: *default-logging
db:
image: postgres:16
environment:
<<: *common-env
POSTGRES_PASSWORD: secret
<<: *default-logging
redis:
image: redis:7-alpine
<<: *default-logging
高级复用模板
x-service-defaults: &service-defaults
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
networks:
- app-net
x-healthcheck-defaults: &healthcheck-defaults
healthcheck:
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
services:
web:
<<: *service-defaults
image: nginx:alpine
ports:
- "80:80"
<<: *healthcheck-defaults
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:80/"]
api:
<<: *service-defaults
build: ./api
ports:
- "8080:3000"
environment:
- DB_HOST=db
depends_on:
- db
<<: *healthcheck-defaults
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
db:
<<: *service-defaults
image: postgres:16
volumes:
- pg-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/db_pass
<<: *healthcheck-defaults
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
networks:
app-net:
volumes:
pg-data:
10.4 Compose Watch(文件监听)
Compose Watch 实时监听文件变化并自动执行操作(开发环境利器)。
services:
web:
build: ./web
develop:
watch:
# 文件变化时同步到容器(不重建)
- action: sync
path: ./web/src
target: /app/src
ignore:
- "**/node_modules"
- "**/*.test.js"
# 依赖文件变化时重建
- action: rebuild
path: ./web/package.json
api:
build: ./api
develop:
watch:
- action: sync+restart
path: ./api
target: /app
ignore:
- "**/__pycache__"
- "**/*.pyc"
Watch 动作类型
| 动作 | 说明 |
|---|---|
sync | 仅同步文件,不重建不重启 |
rebuild | 重建镜像并替换容器 |
sync+restart | 同步文件并重启容器 |
# 启动 Watch 模式
docker compose watch
# 在另一个终端修改文件,观察自动同步
10.5 Secrets(密钥管理)
文件式 Secrets(Swarm 模式)
services:
db:
image: postgres:16
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
app:
build: ./app
secrets:
- db_password
- api_key
secrets:
db_password:
file: ./secrets/db_password.txt
api_key:
file: ./secrets/api_key.txt
# 创建密钥文件
mkdir -p secrets
echo "super-secret-password" > secrets/db_password.txt
echo "my-api-key-12345" > secrets/api_key.txt
chmod 600 secrets/*.txt
# 在容器内读取密钥
docker compose exec app cat /run/secrets/db_password
Secrets vs Environment Variables
| 特性 | Secrets | Environment Variables |
|---|---|---|
| 存储方式 | 文件挂载于 /run/secrets/ | 进程环境变量 |
| 可见性 | docker inspect 不显示 | docker inspect 可见 |
| 大小限制 | 500KB | 无明确限制 |
| 安全性 | 更高 | 较低 |
| 适用场景 | 密码、API Key、证书 | 普通配置变量 |
10.6 Configs(配置管理)
services:
nginx:
image: nginx:alpine
configs:
- source: nginx_conf
target: /etc/nginx/nginx.conf
mode: 0444
configs:
nginx_conf:
file: ./config/nginx.conf
10.7 高级网络配置
services:
app:
networks:
frontend:
aliases:
- app.local
- api.local
ipv4_address: 172.20.0.100
db:
networks:
backend:
ipv4_address: 172.21.0.100
networks:
frontend:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/24
gateway: 172.20.0.1
driver_opts:
com.docker.network.bridge.name: br-frontend
backend:
driver: bridge
internal: true
ipam:
config:
- subnet: 172.21.0.0/24
shared-net:
name: shared-network
external: true # 使用已存在的外部网络
10.8 高级卷配置
services:
app:
volumes:
- type: volume
source: app-data
target: /app/data
volume:
nocopy: true # 不从容器复制数据
- type: bind
source: ./config
target: /app/config
read_only: true
- type: tmpfs
target: /tmp
tmpfs:
size: 100000000 # 100MB
- type: named_pipe
source: //./pipe/docker_engine
target: //./pipe/docker_engine
volumes:
app-data:
driver: local
driver_opts:
type: nfs
o: addr=192.168.1.100,rw,nfsvers=4
device: ":/shared/data"
10.9 Deploy 配置(Swarm 模式)
services:
web:
image: nginx:alpine
deploy:
replicas: 3
update_config:
parallelism: 1 # 每次更新 1 个实例
delay: 30s # 更新间隔
failure_action: rollback
order: start-first # 先启动新实例再停止旧的
rollback_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
resources:
limits:
cpus: "1.0"
memory: 512M
reservations:
cpus: "0.25"
memory: 128M
placement:
constraints:
- node.role == worker
- node.labels.zone == east
10.10 实战:完整的多环境项目
project/
├── compose.yaml # 基础配置
├── compose.override.yaml # 开发覆盖(自动加载)
├── compose.prod.yaml # 生产覆盖
├── compose.test.yaml # 测试覆盖
├── .env # 默认环境变量
├── .env.development # 开发环境变量
├── .env.production # 生产环境变量
├── config/
│ ├── nginx.conf
│ └── prometheus.yml
├── secrets/ # .gitignore 排除
│ ├── db_password.txt
│ └── api_key.txt
└── app/
├── Dockerfile
└── src/
# compose.yaml(基础)
x-logging: &default-logging
logging:
driver: json-file
options: { "max-size": "10m", "max-file": "3" }
services:
app:
build: ./app
<<: *default-logging
depends_on:
db: { condition: service_healthy }
redis: { condition: service_started }
db:
image: postgres:16-alpine
<<: *default-logging
volumes:
- pg-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
retries: 5
redis:
image: redis:7-alpine
<<: *default-logging
volumes:
- redis-data:/data
volumes:
pg-data:
redis-data:
# 开发环境
docker compose up -d
# 测试环境
docker compose -f compose.yaml -f compose.test.yaml up -d
# 生产环境
docker compose -f compose.yaml -f compose.prod.yaml up -d
# 验证最终配置
docker compose -f compose.yaml -f compose.prod.yaml config
要点回顾
| 要点 | 核心内容 |
|---|---|
| 多环境 | 基础文件 + 覆盖文件,或环境变量替换 |
| Profiles | 按需启动服务组,适合开发工具和监控 |
| 扩展字段 | YAML 锚点实现配置复用 |
| Compose Watch | 文件变化自动同步/重建,开发利器 |
| Secrets | 文件式密钥管理,比环境变量更安全 |
注意事项
配置验证: 修改
compose.yaml后,使用docker compose config验证最终配置是否正确。
.env 文件编码:
.env文件必须是 UTF-8 编码,不支持多行值,不支持引号包裹(除非值中包含空格)。
外部网络: 使用
external: true时,网络必须已存在,否则docker compose up会报错。
下一步
→ 11 - Swarm 集群:学习 Docker Swarm 集群管理与服务编排。