docker compose —— 单机多容器编排

运维工具手册 06-容器与编排 6.6 KB 原文

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. 常见坑

  1. version: 字段:v2 不需要,写了会警告,删掉。
  2. depends_on 不等于"就绪":必须配 healthcheck + condition: service_healthy,应用侧仍要重试。
  3. down -v 删数据卷:生产环境执行前确认卷里没有数据。
  4. 改 docker-compose.yml 后没重建:up -d 会检测变化并重建,但只改 image tag 时不会自动 pull,要 pull 或 --pull always。
  5. 容器名冲突:默认项目名是目录名,多套环境在同一台机器要 -p 区分。
  6. .env 不生效:.env 用于 yml 内插值,不是容器环境变量;容器环境变量要用 env_file 或 environment。
  7. environment 里的 $ 被插值:密码含 $ 要写成 $$。
  8. 挂载相对路径:相对于 docker-compose.yml 所在目录,不是执行目录。
  9. 构建缓存导致旧代码:build --no-cache 或 --pull。
  10. 日志无上限:Compose 默认继承 daemon 配置,但显式写在 service 里更保险。
  11. depends_on 循环依赖:Compose 会报错,需要拆服务或去掉依赖。
  12. v1 的 links:已废弃,用网络替代。
  13. 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 限制大小。