docker compose —— 单机多容器编排
docker compose —— 单机多容器编排
分类:06 容器与编排 适用:Compose v2(
docker compose)与 v1(docker-compose) 一句话:一套 YAML 描述应用的所有容器,一条命令拉起、一条命令拆掉。
1. 它解决什么问题
- 一个服务要 web + db + redis + 队列,手工
docker run四条命令且参数易错。 - 开发环境要一键重建,配置要进 Git。
- 容器间网络、依赖顺序、健康检查要统一管理。
生产多机编排用 K8s,单机/小规模用 Compose 完全够。
2. v1 与 v2 的区别
docker compose version # v2,作为 docker 插件(推荐)
docker-compose version # v1,独立 Python 程序(已停止维护)
| 差异 | v1 | v2 |
|---|---|---|
| 命令 | docker-compose up |
docker compose up |
| 文件顶层字段 | 必须写 version: "3.8" |
不需要,写了会警告 |
| 实现 | Python | Go,与 Docker CLI 集成 |
| 性能 | 慢 | 快 |
新环境一律用 v2。
3. 最小可用文件
# docker-compose.yml
services:
web:
image: nginx:1.25
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
depends_on:
- api
restart: unless-stopped
api:
build:
context: ./api
dockerfile: Dockerfile
environment:
DATABASE_URL: postgres://app:secret@db:5432/app
TZ: Asia/Shanghai
depends_on:
db:
condition: service_healthy
restart: unless-stopped
db:
image: postgres:16
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
POSTGRES_DB: app
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d app"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
volumes:
pgdata:
4. 常用命令
docker compose up -d # 后台启动(构建+创建+启动)
docker compose up -d --build # 强制重建镜像
docker compose up -d --force-recreate
docker compose down # 停止并删除容器/网络(保留卷)
docker compose down -v # ⚠️ 同时删除数据卷
docker compose down --rmi local # 同时删除本地镜像
docker compose ps # 状态
docker compose ps -a
docker compose logs -f # 所有服务日志
docker compose logs -f --tail 100 api
docker compose exec api sh # 进容器
docker compose run --rm api python manage.py migrate # 一次性任务
docker compose restart api
docker compose stop / start
docker compose build api
docker compose pull
docker compose config # 校验 + 渲染最终配置(含变量替换)
docker compose top
docker compose images
指定文件与项目名:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
docker compose -p myproj up -d # 项目名决定容器前缀与网络名
多文件叠加是生产常用模式:基础文件 + 环境覆盖文件,后者覆盖前者。
5. 关键字段
depends_on 的两种写法
# 只保证启动顺序,不保证就绪
depends_on:
- db
# 保证健康(推荐)
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
depends_on不会让应用等数据库真正可连接,只是等容器启动/健康检查。应用侧仍需重试逻辑。
环境变量
environment:
- KEY=value
- TZ=Asia/Shanghai
# 或
environment:
KEY: value
env_file:
- .env
- .env.prod
.env 文件(Compose 自动加载,用于文件内变量插值):
TAG=1.2.3
DB_PASSWORD=secret
services:
api:
image: registry/app:${TAG}
environment:
DB_PASSWORD: ${DB_PASSWORD:?必须设置}
:? 表示变量未设置时报错退出,:‑默认值 提供默认。
端口与网络
ports:
- "8080:80" # 宿主:容器
- "127.0.0.1:8080:80" # 只绑本地(安全)
- "8080:80/udp"
networks:
- frontend
- backend
networks:
frontend:
backend:
internal: true # 无外网出口
同一网络内,服务名即主机名(db、api 可互相解析)。
卷
volumes:
- ./conf:/etc/nginx/conf.d:ro # 绑定挂载
- pgdata:/var/lib/postgresql/data # 命名卷
- type: tmpfs
target: /tmp
tmpfs:
size: 100m
资源与日志
services:
api:
deploy:
resources:
limits:
cpus: "1.0"
memory: 1G
reservations:
memory: 256M
logging:
driver: json-file
options:
max-size: "100m"
max-file: "3"
deploy.resources在 Compose v2 单机模式下也生效(不再只用于 Swarm),但replicas不起作用。
profiles(按需启动)
services:
debug:
image: nicolaka/netshoot
profiles: ["debug"]
docker compose up -d # 不启动 debug
docker compose --profile debug up -d # 带上 debug
extends 与锚点
x-common: &common
restart: unless-stopped
logging:
driver: json-file
options: { max-size: "50m" }
services:
a:
<<: *common
image: a:1
b:
<<: *common
image: b:1
6. 实战场景
6.1 开发环境一键拉起
git clone repo && cd repo
cp .env.example .env
docker compose up -d
docker compose ps
docker compose logs -f api
6.2 生产部署(基础 + 覆盖)
docker-compose.prod.yml:
services:
api:
image: registry.example.com/app:1.2.3
build: !reset null # 生产不构建
restart: always
ports:
- "127.0.0.1:8080:8080"
environment:
APP_ENV: prod
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
!reset 是 Compose 2.24+ 语法,用于删除基础文件里的字段。
6.3 数据库迁移(一次性任务)
docker compose run --rm api python manage.py migrate
docker compose run --rm api python manage.py createsuperuser
run 会新建容器,不占用 up 起的那个,--rm 用完即删。
6.4 定位 compose 起不来的原因
docker compose config # 1. 配置语法与变量渲染
docker compose up # 2. 前台跑,直接看报错(不加 -d)
docker compose ps -a # 3. 容器状态与退出码
docker compose logs --tail 100 <svc>
docker inspect <容器名> # 4. 实际配置
6.5 清理
docker compose down # 常规
docker compose down --remove-orphans # 清掉已从 yml 删除的服务
docker compose down -v # ⚠️ 连数据一起删
7. 常见坑
version:字段:v2 不需要,写了会警告,删掉。depends_on不等于"就绪":必须配healthcheck+condition: service_healthy,应用侧仍要重试。down -v删数据卷:生产环境执行前确认卷里没有数据。- 改
docker-compose.yml后没重建:up -d会检测变化并重建,但只改imagetag 时不会自动 pull,要pull或--pull always。 - 容器名冲突:默认项目名是目录名,多套环境在同一台机器要
-p区分。 .env不生效:.env用于 yml 内插值,不是容器环境变量;容器环境变量要用env_file或environment。environment里的$被插值:密码含$要写成$$。- 挂载相对路径:相对于
docker-compose.yml所在目录,不是执行目录。 - 构建缓存导致旧代码:
build --no-cache或--pull。 - 日志无上限:Compose 默认继承 daemon 配置,但显式写在 service 里更保险。
depends_on循环依赖:Compose 会报错,需要拆服务或去掉依赖。- v1 的
links:已废弃,用网络替代。 - Windows 换行:
entrypoint脚本用 CRLF 会报no such file or directory,转 LF。
8. 速查表
docker compose up -d
docker compose up -d --build
docker compose ps -a
docker compose logs -f --tail 100 <svc>
docker compose exec <svc> sh
docker compose run --rm <svc> <cmd>
docker compose restart <svc>
docker compose config
docker compose down
docker compose down -v # ⚠️ 删卷
docker compose -f a.yml -f b.yml up -d
docker compose -p proj up -d
docker compose --profile debug up -d
docker compose pull && docker compose up -d
YAML 写法要点:服务名即主机名;depends_on 配健康检查;ports 绑 127.0.0.1 更安全;别忘 logging 限制大小。