← 全部文章
DockerCompose编排

Docker 系列(七):用 Compose 编排多容器应用

2026年7月22日 · 13 分钟

为什么需要 Compose

上一篇里,跑一个「应用 + 数据库」要手动 docker network create、两三条冗长的 docker run,还得记住一堆参数。要是再加个 Redis 缓存呢?管理起来简直噩梦。

Docker Compose 用一个 docker-compose.yml 文件,把整套服务、网络、数据卷声明式 地定义好,然后:

docker compose up -d    # 一条命令,全部启动
docker compose down     # 一条命令,全部停止清理

提示:新版 Docker 已内置 docker compose(带空格,v2 插件)。老的 docker-compose (带横线,独立命令)仍可用,命令基本一致。

compose 文件结构

看一个「Web 应用 + PostgreSQL + Redis」的完整例子:

services:
  # Web 应用(用当前目录的 Dockerfile 构建)
  web:
    build: .
    ports:
      - "8080:3000"
    environment:
      - DATABASE_URL=postgres://postgres:secret@db:5432/app
      - REDIS_URL=redis://cache:6379
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  # 数据库(直接用现成镜像)
  db:
    image: postgres:16
    environment:
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=app
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Redis 缓存
  cache:
    image: redis:7-alpine
    restart: unless-stopped

# 具名数据卷(由 Compose 管理)
volumes:
  pgdata:

短短几十行,就定义了三个服务、它们的依赖关系、健康检查和数据持久化。

关键字段逐个讲

services —— 定义每个容器

每个 service 就是一个容器。两种来源:

web:
  build: .          # 用本地 Dockerfile 构建
db:
  image: postgres:16   # 直接拉现成镜像

自动组网:服务名即主机名

这是 Compose 最爽的地方:同一个 compose 文件里的服务,会被自动放进一个网络, 可以直接用服务名互访。上面 web 里写的 db:5432cache:6379,其中 dbcache 就是服务名——不用再手动 docker network create,Compose 全帮你做了。

depends_on —— 启动顺序与健康等待

depends_on:
  db:
    condition: service_healthy

让 web 等到 db 健康后再启动。注意:不加 conditiondepends_on 只保证「启动 顺序」,不保证 db 真的「准备好接受连接」——所以要配合下面的 healthcheck。

healthcheck —— 健康检查

healthcheck:
  test: ["CMD-SHELL", "pg_isready -U postgres"]
  interval: 10s      # 每 10 秒检查一次
  timeout: 5s        # 超过 5 秒算失败
  retries: 5         # 连续 5 次失败才算 unhealthy

Docker 定期运行检测命令,判断容器是否真正「可用」,而不只是「进程还活着」。

volumes、environment、restart

  • volumes:挂载数据卷,文件底部要在顶层 volumes: 里声明具名卷。
  • environment:设置环境变量,也可用 env_file: .env 从文件读取。
  • restart: unless-stopped:容器挂了自动重启,除非你手动停。

常用命令

docker compose up -d           # 后台启动全部服务
docker compose up -d --build   # 强制重新构建镜像再启动
docker compose down            # 停止并删除容器、网络
docker compose down -v         # 连数据卷一起删(慎用,会丢数据)
docker compose ps              # 查看服务状态
docker compose logs -f         # 跟踪所有服务日志
docker compose logs -f web     # 只看 web 服务
docker compose exec web sh     # 进入 web 服务容器
docker compose restart web     # 重启单个服务
docker compose pull            # 拉取最新镜像

用 .env 管理配置

把敏感信息和可变配置抽到 .env 文件,别硬编码进 compose:

# .env 文件
POSTGRES_PASSWORD=secret
APP_PORT=8080
# docker-compose.yml 里用 ${} 引用
services:
  web:
    ports:
      - "${APP_PORT}:3000"
  db:
    environment:
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}

Compose 会自动读取同目录下的 .env。记得把 .env 加进 .gitignore,别提交到仓库。

一个真实的开发流程

# 首次启动整套环境
docker compose up -d

# 改了代码,重新构建并更新
docker compose up -d --build

# 看某个服务出了什么问题
docker compose logs -f web

# 进容器调试
docker compose exec web sh

# 今天不干了,全部停掉(数据卷保留)
docker compose down

本篇小结

  • Compose 用一个 YAML 声明式定义多服务,up/down 一键起停整套环境。
  • 同一 compose 文件的服务自动组网,直接用服务名互访。
  • depends_on + healthcheck 控制启动顺序并等待依赖真正就绪。
  • .env + ${变量} 管理配置,敏感信息不入库。

现在你已经能编排一整套应用了。最后一篇进入生产级话题:镜像瘦身、多阶段构建、 安全加固——把前面所有知识收束成可上线的最佳实践。

相关水晶