什么是 Docker Compose
实际应用往往由多个服务组成:前端、后端 API、数据库、缓存、消息队列……手动 docker run 每个服务既繁琐又难以维护。
Docker Compose 是专为单主机多容器应用设计的编排工具。通过一个 compose.yml 文件声明所有服务的配置,然后用一条命令管理整个应用:
docker compose up -d # 后台启动所有服务
docker compose down # 停止并删除所有容器
文件名约定 — 推荐使用 compose.yml(较新规范),也兼容 docker-compose.yml(旧名称)。Docker Compose V2 已内置于 Docker CLI(docker compose,无连字符),旧版独立工具是 docker-compose(有连字符)。
compose.yml 文件结构
# compose.yml 基本结构
services: # 服务定义(必需)
web:
image: nginx:1.25
db:
image: postgres:16
networks: # 自定义网络(可选)
app-net:
driver: bridge
volumes: # 命名卷(可选)
db-data:
核心配置项详解
image vs build
services:
# 使用现有镜像
nginx:
image: nginx:1.25-alpine
# 从 Dockerfile 构建
api:
build:
context: ./api # 构建上下文目录
dockerfile: Dockerfile # Dockerfile 路径(相对于 context)
args:
NODE_ENV: production
# 简写(context 即当前目录)
web:
build: .
ports — 端口映射
services:
web:
image: nginx
ports:
- "8080:80" # 宿主机8080 → 容器80
- "443:443"
- "127.0.0.1:3000:3000" # 只绑定 localhost
volumes — 卷挂载
services:
db:
image: postgres:16
volumes:
- db-data:/var/lib/postgresql/data # 命名卷
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro # 绑定挂载(只读)
volumes:
db-data: # 声明命名卷(在顶层)
environment vs env_file — 环境变量
services:
api:
image: myapi:1.0
# 方式一:直接在 compose.yml 中声明(适合非敏感配置)
environment:
- NODE_ENV=production
- PORT=3000
- LOG_LEVEL=info
# 方式二:从文件加载(敏感配置放 .env 文件,加入 .gitignore)
env_file:
- .env # 默认环境文件
- .env.local # 本地覆盖(不提交到 git)
depends_on — 服务依赖
services:
api:
build: .
depends_on:
db:
condition: service_healthy # 等待 db 健康检查通过
redis:
condition: service_started # 只等待 redis 容器启动(默认)
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
depends_on 只控制启动顺序,不等待服务就绪 — 即使 condition: service_started,数据库容器启动后 PostgreSQL 进程可能还没准备好接受连接。使用 condition: service_healthy 配合 healthcheck 才能真正等待服务就绪。
healthcheck — 健康检查
services:
web:
image: myapp
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s # 每30秒检查一次
timeout: 10s # 超时10秒
retries: 3 # 连续3次失败才标记为不健康
start_period: 40s # 启动后40秒内失败不计入
restart — 重启策略
services:
api:
restart: unless-stopped # 推荐:除非手动停止,否则自动重启
# 可选值:
# no — 不自动重启(默认)
# always — 总是重启(包括 docker daemon 重启)
# on-failure — 仅在退出码非0时重启
# unless-stopped — 手动停止前一直重启
Compose 常用命令
# 启动所有服务(-d 后台,--build 强制重新构建)
docker compose up -d --build
# 停止并删除容器(-v 同时删除命名卷)
docker compose down
docker compose down -v # 危险!删除数据卷
# 只停止,不删除
docker compose stop
docker compose start
# 查看服务状态
docker compose ps
# 查看日志(-f 实时跟踪)
docker compose logs -f
docker compose logs -f api # 只看某个服务
# 进入某个服务的容器
docker compose exec api bash
# 运行一次性命令(不影响现有容器)
docker compose run --rm api npm run migrate
# 只重新构建镜像(不启动)
docker compose build api
# 扩展/缩减服务实例数量
docker compose up --scale api=3
Profile 功能
Profile 允许在不同场景下选择性地启动某些服务:
services:
# 核心服务(总是启动)
api:
build: .
db:
image: postgres:16
# 只在 dev profile 启动
adminer:
image: adminer
profiles: ["dev"]
ports:
- "8080:8080"
# 只在 test profile 启动
test-runner:
build: .
profiles: ["test"]
command: npm test
# 启动核心服务 + dev profile
docker compose --profile dev up -d
# 只运行测试
docker compose --profile test run test-runner
完整实战:全栈 Web 应用
一个包含 React 前端、Node.js API、PostgreSQL 和 Redis 的完整 compose 配置:
# compose.yml
services:
# === 前端(React + Nginx)===
frontend:
build:
context: ./frontend
ports:
- "80:80"
depends_on:
- api
restart: unless-stopped
# === 后端 API(Node.js)===
api:
build:
context: ./api
environment:
- NODE_ENV=production
- PORT=3000
env_file:
- .env
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
restart: unless-stopped
networks:
- frontend-net
- backend-net
# === PostgreSQL 数据库 ===
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: myapp
POSTGRES_PASSWORD: ${DB_PASSWORD} # 从 .env 读取
POSTGRES_DB: myapp
volumes:
- pg-data:/var/lib/postgresql/data
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U myapp"]
interval: 5s
retries: 5
networks:
- backend-net
restart: unless-stopped
# === Redis 缓存 ===
redis:
image: redis:7-alpine
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- redis-data:/data
networks:
- backend-net
restart: unless-stopped
networks:
frontend-net:
backend-net:
volumes:
pg-data:
redis-data:
开发模式:代码热重载
创建 compose.dev.yml 覆盖生产配置,用于本地开发:
# compose.dev.yml(覆盖 compose.yml 的开发配置)
services:
api:
build:
target: dev # 构建到 dev 阶段(含开发工具)
volumes:
- ./api:/app # 挂载代码(热重载)
- /app/node_modules # 不覆盖容器内的 node_modules
command: npm run dev # 覆盖启动命令
environment:
- NODE_ENV=development
frontend:
build:
target: dev
volumes:
- ./frontend:/app
- /app/node_modules
ports:
- "3000:3000" # 开发服务器端口
command: npm start
# 使用多个 compose 文件合并(dev 覆盖 prod)
docker compose -f compose.yml -f compose.dev.yml up -d
本章小结 — Docker Compose 是单机多容器应用开发和部署的首选工具。一个 compose.yml 文件完整描述应用栈,团队成员只需 docker compose up -d 即可在本地跑起完整环境,极大降低了环境配置的协作成本。