FORMA

Docker Compose 编排

Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。通过一个 compose.yml(旧称 docker-compose.yml)配置文件,你可以同时管理多个容器(例如 Web 服务、数据库、缓存等),并使用一条命令启动/停止整个应用栈。容器与网络基础见 容器、数据与网络

一、安装

  • Windows / macOS:Docker Desktop 默认已包含 docker compose(Compose V2,作为 docker CLI 的子命令),无需额外安装。
  • Linux
    bash
    # 通过官方 docker-ce 仓库安装时会自带 compose 插件
    sudo apt update
    sudo apt install docker-compose-plugin -y
    
    # 或安装独立的旧版二进制(V1,命令为 docker-compose,官方已不再更新新特性)
    sudo apt install docker-compose -y
    

验证安装:

bash
docker compose version
# Compose V2 写法,注意 compose 前没有连字符

docker-compose --version
# 旧版 V1 命令,很多教程和脚本里仍能看到

V1 与 V2 的区别:V2 是用 Go 重写、作为 docker 子命令集成的新版本,命令是 docker compose(空格);V1 是独立的 Python 程序,命令是 docker-compose(连字符)。新项目应统一使用 V2,本文命令均以 docker compose 为主,多数场景下把空格换成连字符即对应 V1 写法。

二、compose.yml 基础示例

以下是一个包含 Nginx Web 服务和 Redis 缓存服务的 Compose 文件:

yaml
services: # 定义服务(容器)
  web: # 服务名称
    image: nginx # 使用的镜像
    ports:
      - "8080:80" # 端口映射 宿主机:容器
    volumes:
      - ./html:/usr/share/nginx/html # 挂载本地目录到容器
    depends_on: # 依赖关系(启动顺序,不是等待就绪)
      - redis

  redis:
    image: redis:alpine # 使用轻量版 Redis
    ports:
      - "6379:6379"
    environment: # 环境变量
      - REDIS_PASSWORD=mysecret

字段说明

  • services:定义每个容器,名称可自定义,同一网络内可直接用服务名互相访问(Compose 会自动创建一个专属网络)。
  • image:指定镜像(也可以使用 build 从 Dockerfile 构建)。
  • ports:端口映射。
  • volumes:数据卷或绑定挂载。
  • environment:设置环境变量。
  • depends_on:设置服务依赖(仅影响启动顺序,不保证服务已就绪,需配合健康检查)。

关于 version 字段:Compose V2 已不再需要在文件顶部声明 version: "3.8",写了也会被忽略(并给出弃用提示);新项目建议直接省略。

三、常用命令

所有命令需在 compose.yml 所在目录执行。

命令说明
docker compose up -d后台启动所有服务(-d 守护模式)
docker compose up -d --build启动前先重新构建镜像(build 字段的服务)
docker compose down停止并删除容器、网络(默认保留数据卷)
docker compose down -v同时删除数据卷(-v
docker compose logs -f跟踪所有服务的日志输出
docker compose logs -f web只跟踪指定服务 web 的日志
docker compose ps查看当前项目的服务状态
docker compose exec web bash进入 web 服务的容器中执行命令
docker compose build重新构建服务(用于 build 指令的镜像)
docker compose restart重启所有服务
docker compose stop / start停止 / 启动已存在的服务(不删除容器)
docker compose config验证并查看解析后的最终配置(合并多文件、变量替换后)
docker compose pull拉取所有服务声明的镜像最新版本
docker compose top查看各服务容器内的进程
docker compose scale web=3 / docker compose up -d --scale web=3web 服务扩展到 3 个实例(需服务不绑定固定宿主机端口)

四、常用场景示例

1. 使用 Dockerfile 构建自定义镜像

yaml
services:
  app:
    build: . # 使用当前目录下的 Dockerfile
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production

2. 链接多个服务(Node.js + MongoDB + Redis 多服务示例)

一个更接近真实项目的例子:Node 应用依赖 MongoDB 存储数据、Redis 做缓存,并通过环境变量文件和健康检查确保依赖服务就绪后才启动应用。

yaml
services:
  web:
    build: .
    ports:
      - "3000:3000"
    env_file:
      - .env # 从文件读取环境变量,避免敏感信息写入 compose.yml
    environment:
      - MONGO_URL=mongodb://mongo:27017/app
      - REDIS_URL=redis://redis:6379
    depends_on:
      mongo:
        condition: service_healthy # 等待 mongo 健康检查通过再启动
      redis:
        condition: service_started
    restart: unless-stopped

  mongo:
    image: mongo:7
    volumes:
      - mongo-data:/data/db # 命名卷,持久化数据库文件
    healthcheck:
      test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    volumes:
      - redis-data:/data
    restart: unless-stopped

volumes:
  mongo-data: # 声明卷,由 Docker 管理
  redis-data:

要点

  • depends_on 配合 condition: service_healthy 才能真正「等待服务就绪」,仅声明依赖名不会等待应用初始化完成。
  • env_file 把配置和密钥从版本控制中分离,配合 .gitignore 忽略 .env 文件。
  • restart: unless-stopped 让服务在宿主机重启或异常退出后自动恢复,但手动 docker compose stop 不会被自动拉起。

3. 多环境配置(开发 / 生产覆盖)

Compose 支持多文件叠加,常见做法是把公共配置放在 compose.yml,环境差异放在 compose.override.yml(默认自动加载)或显式指定的文件中。

yaml
# compose.yml(生产基线)
services:
  web:
    build: .
    restart: always
yaml
# compose.override.yml(本地开发,默认自动与上面合并)
services:
  web:
    volumes:
      - .:/app # 挂载源码实现热更新
    environment:
      - NODE_ENV=development
    command: npm run dev
bash
# 默认会自动加载 compose.yml + compose.override.yml
docker compose up -d

# 生产环境显式只用基线文件,忽略 override
docker compose -f compose.yml up -d

# 显式叠加多个文件(顺序即优先级,后者覆盖前者)
docker compose -f compose.yml -f compose.prod.yml up -d

4. 使用 .env 文件做变量替换

Compose 会自动读取同目录下的 .env 文件,用于替换 compose.yml 中的 ${VAR} 占位符(区别于 env_file,后者是把内容注入到容器环境变量)。

text
# .env
IMAGE_TAG=1.25
WEB_PORT=8080
yaml
services:
  web:
    image: nginx:${IMAGE_TAG}
    ports:
      - "${WEB_PORT}:80"

五、常见排错

现象可能原因与排查方法
docker compose up 后容器立即退出查看 docker compose logs <service> 看应用报错;确认镜像的 CMD/ENTRYPOINT 不是一次性任务(如未加 -d 前台运行的临时命令)
服务之间无法互相访问确认使用服务名而非 localhost 通信(Compose 内部通过服务名 DNS 解析);确认服务在同一个 Compose 项目/网络中
端口冲突:port is already allocated宿主机端口已被占用,改用其他宿主机端口,或用 docker ps / lsof -i:端口号 排查占用进程
修改了 compose.yml 但不生效需要重新 docker compose up -d(会重建有变化的服务);镜像本身变化需先 docker compose build 或加 --build
数据卷里是旧数据卷的生命周期独立于容器,docker compose down 默认不会删除卷;确认是否需要 -v 一并清理,或直接 docker volume rm
depends_on 似乎没等服务就绪默认 depends_on 只保证启动顺序,不保证应用初始化完成,需配合 healthcheck + condition: service_healthy,或在应用层做重试连接逻辑
权限错误,容器内无法写挂载目录检查宿主机目录权限与容器内运行用户的 UID/GID 是否匹配,或以 --user $(id -u):$(id -g) 运行
docker compose 命令找不到Compose V2 未安装为插件;确认 docker compose version 是否有输出,或改用 docker-compose(V1,需单独安装)
构建后容器仍使用旧代码docker compose build 时缓存了旧的层;用 docker compose build --no-cache 或调整 Dockerfile 中 COPY 顺序(见 镜像与 Dockerfile

排错的通用思路:先用 docker compose ps 确认哪个服务状态异常,再用 docker compose logs -f <service> 看具体报错,配合 docker compose config 检查变量替换和多文件合并后的最终配置是否符合预期。

六、总结

  • Docker Compose 简化了多容器应用的编排,适合开发、测试和中小规模生产部署。
  • 通过一个 compose.yml 文件定义服务、网络、数据卷,使用一条命令即可管理整个应用栈。
  • 常用命令:updownlogsexecbuild 等,结合 -d 可实现后台运行;depends_on + healthcheck 才能真正保证依赖服务就绪。
  • 多文件叠加(compose.override.yml-f 多文件)与 .env 变量替换,可以优雅地管理开发/生产等多环境差异。
  • Compose 可与单机 Docker 无缝配合,但不适用于跨多主机的集群(需要使用 Docker Swarm 或 Kubernetes)。

掌握 Docker Compose,可以高效地管理复杂应用的多容器依赖,提升开发和部署效率。

参考文献

资料说明
Docker Compose 文档官方
Compose 文件参考完整字段说明
Compose 健康检查依赖depends_on + healthcheck
运维导读学习路径

相关文章

Series

docker

1 / 4