引言
单个容器用 docker run 就能跑,但真实项目几乎从不是单容器——Web 服务要连数据库、缓存、消息队列,可能还有 Nginx 反代、后台任务。如果靠手动敲 docker run 并逐个管理网络、数据卷、启动顺序,很快会陷入"启动要十几条命令、还容易漏"的泥潭。
Docker Compose 就是为解决这个问题而生: 用一份 YAML 文件描述整个应用栈,一条命令统一启停、编排。这篇指南覆盖从入门语法到生产实践,助你把多容器管理变成一件轻松事。
前置:确认环境已安装 Compose,
docker compose version能输出版本即可。Docker Desktop(Win/Mac)自带,Linux 上 Docker Engine 20.10+ 也已内置。
一、认识 Compose 与 v1→v2 迁移
1.1 Compose 能做什么
一键编排:
docker compose up即可启动定义的所有服务。统一管理网络与数据卷:Compose 自动为项目创建独立网络,容器间可直接用服务名互访。
声明式配置:应用栈的全部依赖关系都写进 YAML,可版本化、可复现、可提交到 Git。
1.2 重要变化:Compose v1 → v2
Docker Compose 已从 v1(独立的 docker-compose 命令,Python 编写)全面迁移到 v2(Go 重写,集成进 Docker CLI)。关键变化:
# 旧写法(v1,已弃用)
docker-compose up -d
# 新写法(v2,推荐)
docker compose up -d # 注意:是空格,不是连字符迁移建议:脚本中全局替换 docker-compose 为 docker compose;新项目优先使用 compose.yaml 命名。
二、compose.yaml 语法详解
这是 Compose 的核心,掌握语法就等于掌握了 Compose 90% 的用法。
2.1 顶级元素
一份 compose.yaml 通常包含以下顶级元素:
2.2 一个最小示例
services:
web:
image: nginx:1.25
ports:
- "8080:80"docker compose up -d 即可启动一个映射到宿主机 8080 端口的 Nginx。
2.3 service 常用配置项
2.4 build 的两种写法
# 简单写法:构建上下文为当前目录
services:
web:
build: .
# 完整写法:指定上下文和 Dockerfile、构建参数
services:
web:
build:
context: ./web
dockerfile: Dockerfile.dev
args:
NODE_ENV: production2.5 环境变量与变量替换
Compose 支持在 YAML 中使用 ${VAR} 引用环境变量,非常适合区分环境:
services:
web:
image: myapp:${APP_TAG:-latest}
environment:
DB_HOST: db
DB_PASSWORD: ${DB_PASSWORD}${VAR:-default}:变量未设置时使用默认值。Compose 会自动读取项目根目录下的
.env文件作为默认环境变量来源。
2.6 扩展字段复用(x-)
v2 支持用 x- 前缀定义可复用的配置片段,减少重复:
x-common-env: &common-env
environment:
- TZ=Asia/Shanghai
- LOG_LEVEL=info
services:
web:
image: myapp:1.0
<<: *common-env
worker:
image: myapp:1.0
<<: *common-env三、常用命令详解
3.1 启动与停止
# 构建并后台启动所有服务
docker compose up -d
# 仅构建镜像(不启动)
docker compose build
# 构建指定服务
docker compose build web
# 强制重新构建后启动(不读取缓存)
docker compose up -d --build
# 停止服务(保留容器)
docker compose stop
# 停止并删除容器、网络(默认不删数据卷)
docker compose down
# 连同数据卷一起删除(慎用)
docker compose down -v3.2 查看状态与日志
# 查看项目服务状态
docker compose ps
# 查看日志(-f 跟随,--tail 限制行数)
docker compose logs -f --tail 100
# 只查看某个服务的日志
docker compose logs web3.3 操作单个服务
# 在指定服务中执行命令(进入 shell)
docker compose exec web bash
# 运行一次性命令
docker compose run --rm web python manage.py migrate
# 重启 / 启动 / 停止指定服务
docker compose restart web
docker compose start web
docker compose stop web3.4 查看与校验配置
# 查看合并后的最终配置(校验语法 + 预览)
docker compose config
# 列出所有 Compose 项目(v2 新特性)
docker compose ls四、实战案例:部署 Web + MySQL + Redis
下面是一个贴近真实开发的项目:一个 Web 应用 + MySQL 数据库 + Redis 缓存 + Nginx 反向代理。
4.1 项目结构
myapp/
├── compose.yaml
├── .env
├── web/
│ ├── Dockerfile
│ └── app.py
└── nginx/
└── nginx.conf4.2 compose.yaml
services:
web:
build: ./web
restart: unless-stopped
environment:
DB_HOST: db
DB_PASSWORD: ${DB_PASSWORD}
REDIS_HOST: redis
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
networks:
- app-net
db:
image: mysql:8.0
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: myapp
volumes:
- db-data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app-net
redis:
image: redis:7-alpine
restart: unless-stopped
networks:
- app-net
nginx:
image: nginx:1.25
restart: unless-stopped
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- web
networks:
- app-net
networks:
app-net:
volumes:
db-data:4.3 .env
DB_PASSWORD=your-secret-password4.4 启动与验证
# 一键启动整个应用栈
docker compose up -d
# 查看状态
docker compose ps
# 查看 web 服务日志
docker compose logs -f web4.5 案例要点解析
depends_on** 的两种条件**:service_healthy表示等待 db 健康检查通过后才启动 web,比单纯的service_started(仅等容器启动)更可靠,能避免"数据库还没就绪应用就连不上"的经典问题。数据卷
db-data:确保docker compose down后数据库数据不丢失。网络隔离:所有服务在自定义网络
app-net内,通过服务名(db、redis)互访,Nginx 只对外暴露 80 端口。
五、最佳实践与常见排错
5.1 最佳实践
配置文件用
compose.yaml,与项目代码一起纳入版本控制。敏感信息用
.env:数据库密码等不要硬编码在 YAML 里,用${VAR}引用,.env加入.gitignore。生产显式指定 tag:避免
latest带来的不确定性。用好
depends_on** +**healthcheck:确保服务启动顺序和就绪状态。数据持久化用命名卷:数据库、文件存储等服务务必挂载 volume。
5.2 常见问题排查
总结与展望
Docker Compose 把"多容器应用的编排"从一堆手工命令,变成了一份可读、可版本化、可复现的 YAML 声明。掌握本指南的语法要点和常用命令,你就能覆盖绝大多数开发与测试场景:
用
compose.yaml** 描述应用栈**,而非手敲docker run。用
depends_on** +**healthcheck** 管好启动顺序**。用
.env** 和变量替换隔离敏感信息与多环境差异**。
随着项目规模增长,同一套 compose.yaml 还可以平滑迁移到 Docker Swarm 或 Kubernetes(借助 Kompose 等工具),学习成本不高,长期收益明显。
延伸阅读:Docker 镜像、容器、网络、存储等核心命令,请参阅《Docker 常用命令速查手册:镜像、容器、网络与存储》。
参考资料: