Docker 完全指南 / 09 - Compose 基础
09 - Compose 基础
使用 Docker Compose 定义和管理多容器应用,实现一键启动开发环境。
9.1 Docker Compose 简介
Docker Compose 是一个多容器编排工具,使用 YAML 文件定义应用的服务、网络和卷,然后用一条命令启动整个应用栈。
传统方式 (繁琐):
docker network create my-net
docker volume create db-data
docker run -d --name db --network my-net -v db-data:/var/lib/mysql ...
docker run -d --name redis --network my-net ...
docker run -d --name app --network my-net -p 8080:80 ...
Compose 方式 (简洁):
docker compose up -d # 一条命令搞定一切
Compose 文件版本演进
| 版本 | 说明 |
|---|---|
| Compose V1 | docker-compose 命令,Python 实现,已废弃 |
| Compose V2 | docker compose 命令(无连字符),Go 实现,当前主流 |
| Compose Spec | 2020 年合并入 Docker 规范,无需指定 version 字段 |
# 检查 Compose 版本
docker compose version
# V1 (已废弃)
docker-compose --version
# V2 (推荐)
docker compose version
9.2 compose.yaml 文件结构
基本结构
# compose.yaml (或 docker-compose.yml)
services: # 服务定义
web:
...
db:
...
networks: # 网络定义(可选)
...
volumes: # 卷定义(可选)
...
configs: # 配置定义(可选)
...
secrets: # 密钥定义(可选)
...
最小示例
services:
web:
image: nginx:alpine
ports:
- "8080:80"
# 启动
docker compose up -d
# 查看状态
docker compose ps
# 停止
docker compose down
9.3 服务配置详解
完整服务配置
services:
web:
# 镜像来源 (二选一)
image: nginx:alpine
# build: ./web # 从 Dockerfile 构建
# 容器名称
container_name: my-web
# 端口映射
ports:
- "8080:80"
- "8443:443"
- "127.0.0.1:9090:9090"
# 环境变量
environment:
- NODE_ENV=production
- DB_HOST=db
# 或使用文件
# env_file:
# - .env
# 数据卷
volumes:
- ./html:/usr/share/nginx/html:ro
- nginx-logs:/var/log/nginx
# 网络
networks:
- frontend
# 依赖关系
depends_on:
- db
- redis
# 重启策略
restart: unless-stopped
# 资源限制
deploy:
resources:
limits:
cpus: "1.0"
memory: 512M
# 健康检查
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
# 日志配置
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
# 标签
labels:
- "traefik.enable=true"
- "app.version=1.0"
常用配置项速查
| 配置项 | 说明 | 示例 |
|---|---|---|
image | 使用的镜像 | nginx:alpine |
build | 从 Dockerfile 构建 | ./app 或详细配置 |
ports | 端口映射 | "8080:80" |
environment | 环境变量 | KEY=value |
env_file | 环境变量文件 | .env |
volumes | 数据卷/挂载 | data:/app/data |
networks | 加入的网络 | frontend |
depends_on | 启动依赖 | [db, redis] |
restart | 重启策略 | unless-stopped |
command | 覆盖默认命令 | ["npm", "start"] |
entrypoint | 覆盖入口点 | /entrypoint.sh |
working_dir | 工作目录 | /app |
user | 运行用户 | node:node |
stdin_open | 打开 stdin | true |
tty | 分配 TTY | true |
profiles | 配置文件组 | [debug, test] |
9.4 实战:Web + DB 应用栈
目录结构
my-project/
├── compose.yaml
├── .env
├── app/
│ ├── Dockerfile
│ └── src/
│ └── ...
└── db/
└── init.sql
compose.yaml
services:
# ---- 应用服务 ----
app:
build: ./app
container_name: my-app
ports:
- "8080:3000"
environment:
- NODE_ENV=production
- DB_HOST=db
- DB_PORT=5432
- DB_NAME=${POSTGRES_DB}
- DB_USER=${POSTGRES_USER}
- DB_PASS=${POSTGRES_PASSWORD}
volumes:
- ./app/src:/app/src:ro
- app-uploads:/app/uploads
depends_on:
db:
condition: service_healthy
restart: unless-stopped
networks:
- frontend
- backend
# ---- 数据库服务 ----
db:
image: postgres:16-alpine
container_name: my-db
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
volumes:
- pg-data:/var/lib/postgresql/data
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- backend
# ---- Redis 缓存 ----
redis:
image: redis:7-alpine
container_name: my-redis
command: redis-server --appendonly yes
volumes:
- redis-data:/data
restart: unless-stopped
networks:
- backend
# ---- 网络定义 ----
networks:
frontend:
backend:
# ---- 卷定义 ----
volumes:
pg-data:
redis-data:
app-uploads:
.env 文件
# .env
POSTGRES_USER=admin
POSTGRES_PASSWORD=supersecret
POSTGRES_DB=myapp
启动与管理
# 一键启动所有服务
docker compose up -d
# 查看服务状态
docker compose ps
# 查看日志
docker compose logs
docker compose logs -f app # 跟踪指定服务日志
docker compose logs --tail 50 # 最近 50 行
# 查看资源使用
docker compose top
docker stats
# 进入容器
docker compose exec app sh
docker compose exec db psql -U admin -d myapp
# 停止所有服务
docker compose down
# 停止并删除卷(数据会丢失!)
docker compose down -v
9.5 构建配置
基本构建
services:
app:
build:
context: ./app
dockerfile: Dockerfile
image: my-app:latest
详细构建配置
services:
app:
build:
context: .
dockerfile: docker/Dockerfile.prod
target: production # 多阶段构建目标
args: # 构建参数
NODE_ENV: production
APP_VERSION: "1.0.0"
cache_from: # 缓存来源
- my-app:latest
labels: # 镜像标签
- "app.version=1.0.0"
platforms: # 多架构
- linux/amd64
- linux/arm64
image: my-app:latest # 构建后的镜像名
# 构建镜像
docker compose build
# 强制重建(不使用缓存)
docker compose build --no-cache
# 构建并启动
docker compose up --build
# 仅构建指定服务
docker compose build app
9.6 网络配置
默认网络
# 不定义 networks 时,Compose 自动创建默认网络
# 网络名: <项目名>_default
services:
web:
image: nginx:alpine
db:
image: postgres:16
# web 和 db 自动在同一默认网络中,可通过服务名访问
自定义网络
services:
web:
networks:
- frontend
api:
networks:
- frontend
- backend
db:
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 仅内部通信,无法访问外部网络
9.7 依赖管理
depends_on
services:
app:
depends_on:
db:
condition: service_healthy # 等待健康检查通过
redis:
condition: service_started # 仅等待启动
migration:
condition: service_completed_successfully # 等待完成
migration:
build: ./app
command: python manage.py migrate
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
interval: 5s
retries: 10
redis:
image: redis:7-alpine
depends_on 条件
| 条件 | 说明 |
|---|---|
service_started | 服务已启动(默认) |
service_healthy | 服务健康检查通过 |
service_completed_successfully | 服务成功退出(退出码 0) |
9.8 环境变量
方式一: environment 字段
services:
app:
environment:
- NODE_ENV=production
- DB_HOST=db
- SECRET_KEY=abc123
方式二: env_file 字段
services:
app:
env_file:
- .env
- .env.local # 可指定多个文件
方式三: .env 文件(自动加载)
Compose 会自动加载项目目录下的 .env 文件中的变量,用于 compose.yaml 中的变量替换。
# .env
POSTGRES_USER=admin
POSTGRES_PASSWORD=secret
# compose.yaml
services:
db:
image: postgres:16
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
变量优先级
优先级从高到低:
1. docker compose run -e 设置的变量
2. Shell 环境变量 (export)
3. env_file 文件中的变量
4. compose.yaml 中 environment 字段
5. Dockerfile 中 ENV 定义的变量
6. .env 文件中的变量(仅用于 compose.yaml 变量替换)
9.9 Compose 命令大全
生命周期命令
# 创建并启动所有服务
docker compose up -d
# 创建并启动指定服务
docker compose up -d app db
# 强制重建镜像并启动
docker compose up --build --force-recreate
# 停止所有服务
docker compose stop
# 停止并删除容器、网络
docker compose down
# 停止并删除容器、网络、卷
docker compose down -v
# 停止并删除容器、网络、卷、镜像
docker compose down -v --rmi all
# 重启服务
docker compose restart app
# 暂停/恢复服务
docker compose pause
docker compose unpause
查看命令
# 查看服务状态
docker compose ps
docker compose ps -a # 包含已停止的
# 查看日志
docker compose logs -f --tail 100
# 查看进程
docker compose top
# 查看资源使用
docker compose stats
# 验证配置文件
docker compose config
# 列出镜像
docker compose images
执行命令
# 在运行中的容器内执行命令
docker compose exec app bash
docker compose exec db psql -U admin
# 运行一次性命令(创建新容器)
docker compose run --rm app python manage.py test
docker compose run --rm app npm install
# exec vs run 的区别:
# exec: 进入已运行的容器
# run: 创建新容器执行命令(使用 --rm 自动清理)
9.10 Compose 配置文件名
# 默认查找顺序:
# 1. compose.yaml (推荐)
# 2. compose.yml
# 3. docker-compose.yaml
# 4. docker-compose.yml
# 指定配置文件
docker compose -f compose.prod.yaml up -d
# 使用多个配置文件(合并)
docker compose -f compose.yaml -f compose.prod.yaml up -d
# 指定项目名称
docker compose -p my-project up -d
要点回顾
| 要点 | 核心内容 |
|---|---|
| compose.yaml | 定义服务、网络、卷的声明式配置文件 |
| 服务发现 | 同一 Compose 项目中的服务可通过服务名互相访问 |
| depends_on | 控制服务启动顺序,支持健康检查条件 |
| 环境变量 | 支持 environment、env_file、.env 三种方式 |
| 常用命令 | up -d 启动、down 停止、logs -f 日志、exec 执行 |
注意事项
文件名推荐: 新项目使用
compose.yaml(无 docker- 前缀),这是 Docker 官方推荐的命名。
不要存储密码:
.env文件不要提交到 Git。使用.env.example作为模板,并在.gitignore中排除.env。
depends_on 不等待就绪:
service_started仅表示容器已启动,不代表应用已就绪。务必配合健康检查使用service_healthy。
下一步
→ 10 - Compose 进阶:学习多环境配置、Profiles、扩展字段等高级特性。