🔍搜索⌘K

Docker Compose 命令全指南:从配置文件到实战操作

概述

在 Docker 单机环境中,若要运行 多容器协作的应用(如 “前端服务 + 后端服务 + 数据库 + 缓存”),手动用 docker run 启动每个容器、配置网络和数据卷会非常繁琐 —— 不仅要记清每个容器的参数,还需确保容器启动顺序正确(如先启数据库,再启后端)。

Docker Compose 正是为解决这一问题而生的编排工具:它通过一个 docker-compose.yml 配置文件,集中定义所有容器的 “镜像、端口、网络、数据卷、依赖关系”,再用一条命令即可完成 “创建、启动、停止、销毁” 全流程,大幅简化多容器应用的管理成本。

其核心优势:

  1. 配置即代码:用 YAML 文件固化容器配置,便于版本控制和团队协作;
  2. 一键操作:单条命令管理所有容器(启动、停止、重启),无需逐个操作;
  3. 环境一致性:确保开发、测试、生产环境的容器配置一致,避免 “在我电脑上能跑” 的问题;
  4. 依赖管理:支持定义容器启动顺序(如 depends_on 确保数据库先启动)。

一、基础:Docker Compose 配置文件(docker-compose.yml)

docker-compose.yml 是 Compose 的核心,所有容器的配置都集中在此。下面以 “投票应用(含 Redis、PostgreSQL、前端、后端、worker)” 为例,解析配置文件的核心结构和常用字段,帮你快速理解如何编写自己的配置。

1. 完整配置示例(含关键注释)

# 1. 指定 Compose 文件版本(需与 Docker 版本兼容,3.9 适配 Docker 20.10+)
version: "3.9"

# 2. 定义所有服务(每个 service 对应一个容器)
services:
  # 服务1:Redis 缓存(用于存储投票数据)
  redis:
    image: redis:alpine # 使用轻量的 alpine 镜像,减少体积
    ports:
      - "6379:6379" # 端口映射:主机 6379 → 容器 6379(可省略,内部网络可直接访问)
    networks:
      - frontend # 加入 frontend 网络,与前端服务通信
    deploy:
      replicas: 2 # 启动 2 个 Redis 副本(仅在 Swarm 模式生效,单机模式忽略)
      update_config: # 滚动更新配置(更新时并行启动 2 个副本,间隔 10 秒)
        parallelism: 2
        delay: 10s
      restart_policy: # 重启策略:容器故障时自动重启
        condition: on-failure

  # 服务2:PostgreSQL 数据库(用于存储最终投票结果)
  db:
    image: postgres:9.4 # 指定 PostgreSQL 版本,避免版本兼容问题
    volumes:
      - db-data:/var/lib/postgresql/data # 数据卷挂载:持久化数据库数据(容器删除后数据不丢失)
    networks:
      - backend # 加入 backend 网络,与后端服务通信
    deploy:
      placement:
        # 约束:仅在 Docker Swarm 的 manager 节点启动(单机模式忽略)
        constraints: [node.role == manager]
    environment: # 补充:添加环境变量(如数据库密码,实际项目建议用 .env 文件)
      - POSTGRES_PASSWORD=123456
      - POSTGRES_DB=voting

  # 服务3:投票前端服务(用户提交投票的页面)
  vote:
    image: dockersamples/examplevotingapp_vote:before
    ports:
      - "5000:80" # 主机 5000 端口 → 容器 80 端口(前端服务默认用 80)
    networks:
      - frontend
    depends_on:
      - redis # 依赖 redis:启动 vote 前先启动 redis(仅保证顺序,不等待服务就绪)
    deploy:
      replicas: 2 # 启动 2 个前端副本,实现负载均衡
      update_config:
        parallelism: 2

  # 服务4:投票结果展示服务(显示最终投票结果)
  result:
    image: dockersamples/examplevotingapp_result:before
    ports:
      - "5001:80" # 主机 5001 端口 → 容器 80 端口
    networks:
      - backend
    depends_on:
      - db # 依赖 db:启动 result 前先启动数据库
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure

  # 服务5:worker 服务(处理投票数据,从 Redis 同步到 PostgreSQL)
  worker:
    image: dockersamples/examplevotingapp_worker
    networks:
      - frontend # 同时加入两个网络,实现 Redis 和 PostgreSQL 通信
      - backend
    deploy:
      mode: replicated # 复制模式(默认),与 global(每个节点一个副本)对应
      labels: [APP=VOTING] # 添加标签,便于筛选和管理
      restart_policy:
        condition: on-failure
        delay: 10s # 故障后延迟 10 秒重启
        max_attempts: 3 # 最多重试 3 次
        window: 120s # 120 秒内多次故障则停止重启

  # 服务6:可视化工具(查看容器运行状态)
  visualizer:
    image: dockersamples/visualizer:stable
    ports:
      - "8080:8080" # 主机 8080 端口 → 容器 8080 端口(可视化页面)
    stop_grace_period: 1m30s # 停止容器前等待 1 分 30 秒(确保数据清理完成)
    volumes:
      # 挂载 Docker 守护进程套接字,用于获取容器状态(可视化工具必需)
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints: [node.role == manager]

# 3. 定义网络(用于隔离不同服务的通信,如 frontend 供前端服务,backend 供后端服务)
networks:
  frontend: # 无需额外配置,默认使用 bridge 网络模式
  backend:

# 4. 定义数据卷(用于持久化数据,db-data 对应 db 服务的数据库数据)
volumes:
  db-data: # 默认使用 local 驱动,数据存储在主机 /var/lib/docker/volumes/ 目录

2. 核心配置字段解读(必掌握)

字段作用说明
versionCompose 文件版本,需与 Docker 版本匹配(推荐 3.8+,适配主流 Docker 版本)
services核心节点,每个子节点对应一个容器(服务名可自定义,如 redis、db)
image容器使用的镜像(格式:镜像名:标签,如 redis:alpine)
ports端口映射(格式:主机端口:容器端口,如 5000:80)
volumes数据卷挂载(支持 “命名卷” 如 db-data:/path 和 “绑定挂载” 如 ./data:/path)
networks容器加入的网络(实现服务间通信,同一网络内可通过服务名访问)
depends_on容器启动顺序(如 vote 依赖 redis,确保 redis 先启动)
environment环境变量(可直接写值或引用 .env 文件变量,如 POSTGRES_PASSWORD=${DB_PWD})
deploy部署配置(如 replicas 副本数、restart_policy 重启策略,Swarm 模式生效)

二、Docker Compose 命令实战(按使用频率排序)

Docker Compose 命令的基本格式为: docker-compose [选项] 命令 [服务名]

其中 选项 常用 -f(指定配置文件)和 -p(指定项目名,避免同名冲突);服务名 可选,不指定则对所有服务生效。

1. 启动服务:docker-compose up(最常用)

功能:创建并启动配置文件中定义的服务(若镜像不存在,自动拉取)。

# 1. 基础用法:前台启动所有服务(日志实时输出,按 Ctrl+C 停止)
docker-compose up

# 2. 后台启动(推荐):-d(detach)表示后台运行,不占用终端
docker-compose up -d

# 3. 启动指定服务(如仅启动 redis 和 db,适合调试单个服务)
docker-compose up -d redis db

# 4. 指定配置文件(默认找当前目录的 docker-compose.yml,-f 指定自定义路径)
docker-compose -f ./configs/my-compose.yml up -d

# 5. 指定项目名(-p,避免多个项目同名冲突,如区分“test-vote”和“prod-vote”)
docker-compose -f my-compose.yml -p test-vote up -d

# 6. 动态指定配置(通过管道传递配置内容,无需本地文件,适合脚本)
cat << EOF | docker-compose -f - up -d
version: "3.9"
services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
EOF

# 7. 扩展服务副本数(--scale,单机模式下临时扩展,Swarm 模式用 deploy.replicas)
# 示例:将 vote 服务扩展到 3 个副本
docker-compose up -d --scale vote=3

2. 停止服务:docker-compose down(清理资源)

功能:停止并删除容器、网络(数据卷默认保留,避免数据丢失)。

# 1. 基础用法:停止并删除容器和网络,保留数据卷
docker-compose down

# 2. 彻底清理(含数据卷):-v(volume)删除命名数据卷,谨慎使用!
docker-compose down -v

# 3. 清理镜像:--rmi all 删除 Compose 管理的所有镜像(避免占用空间)
docker-compose down --rmi all

# 4. 指定配置文件和项目名(与 up 命令对应,确保操作目标正确)
docker-compose -f my-compose.yml -p test-vote down -v

3. 查看容器状态:docker-compose ps

功能:查看 Compose 管理的容器状态(运行 / 停止、端口、容器 ID 等)。

# 1. 查看所有服务的容器状态
docker-compose ps

# 2. 查看指定服务(如仅看 vote 服务的容器)
docker-compose ps vote

# 3. 仅输出容器 ID(-q,quiet),适合后续脚本操作(如批量进入容器)
docker-compose ps -q vote  # 输出所有 vote 容器的 ID

4. 查看日志:docker-compose logs

功能:查看容器的日志输出(支持实时跟踪,适合排查问题)。

# 1. 查看所有服务的日志(默认输出所有历史日志)
docker-compose logs

# 2. 查看指定服务的日志(如仅看 backend 服务的日志)
docker-compose logs backend

# 3. 实时跟踪日志(-f,follow):类似 tail -f,日志新增时实时输出
docker-compose logs -f vote

# 4. 查看最新日志(--tail,如仅看最后 100 行)
docker-compose logs --tail=100 db

5. 进入容器:docker-compose exec

功能:进入运行中的容器,执行命令(类似 docker exec,但无需记容器 ID,直接用服务名)。

# 1. 进入指定服务的容器,启动 bash 终端(如进入 db 容器)
docker-compose exec db bash

# 2. 执行单个命令(无需进入终端,如查看 db 容器的进程)
docker-compose exec db ps aux

# 3. 进入多副本服务的指定实例(--index,如进入第 2 个 vote 容器)
docker-compose exec --index 2 vote bash

# 4. 传递环境变量(-e,如在容器中设置临时环境变量)
docker-compose exec -e DEBUG=1 vote bash

6. 重启服务:docker-compose restart

功能:重启运行中的服务(比 down + up 更轻量,无需重新创建容器)。

# 1. 重启所有服务
docker-compose restart

# 2. 重启指定服务(如仅重启 worker 服务)
docker-compose restart worker

# 3. 延迟重启(-t,指定停止容器前的等待时间,单位:秒)
# 示例:重启 db 服务前等待 5 秒,确保数据写入完成
docker-compose restart -t 5 db

7. 拉取镜像:docker-compose pull

功能:提前拉取配置文件中的所有镜像(避免 up 时等待拉取,适合网络慢的环境)。

# 1. 拉取所有服务的镜像
docker-compose pull

# 2. 拉取指定服务的镜像(如仅拉取 redis 和 postgres)
docker-compose pull redis db

8. 其他高频命令(按场景分类)

(1)容器操作(启动 / 停止 / 删除)

# 启动已停止的服务(不创建新容器,仅恢复运行)
docker-compose start redis

# 停止运行中的服务(不删除容器,可通过 start 恢复)
docker-compose stop redis
# 延迟停止:-t 5 表示等待 5 秒后停止
docker-compose stop -t 5 redis

# 删除已停止的容器(-f 强制删除运行中的容器,-v 删除关联数据卷)
docker-compose rm -f -v redis

(2)配置验证与镜像管理

# 验证配置文件语法(config,检查 YAML 格式是否正确,避免 up 时报错)
docker-compose config
# 显示详细配置(--services 列出所有服务名,--volumes 列出所有数据卷)
docker-compose config --services

# 查看 Compose 管理的所有镜像(images,含镜像名、标签、大小)
docker-compose images

(3)容器状态监控

# 查看容器内的进程(top,类似 Linux top 命令)
docker-compose top vote  # 查看 vote 服务容器的进程

# 暂停容器(pause):暂停服务运行,不释放资源
docker-compose pause redis
# 恢复暂停的容器(unpause)
docker-compose unpause redis

(4)版本与帮助

# 查看 Docker Compose 版本(确认是否支持所需功能)
docker-compose version

# 查看命令帮助(如查看 up 命令的所有选项)
docker-compose up --help

9. 冷门但实用的命令:docker-compose run

功能:临时运行一个一次性容器(基于服务配置,可覆盖部分参数,适合调试)。

# 1. 基于 vote 服务配置,临时运行一个容器并执行命令(如查看环境变量)
docker-compose run vote env

# 2. 暴露服务端口(--service-ports,使用配置文件中的 ports 映射)
# 示例:临时启动 vote 容器并暴露 5000 端口,用于测试
docker-compose run --service-ports vote

# 3. 自定义端口映射(-p,覆盖配置文件中的 ports)
# 示例:临时将主机 5002 端口映射到容器 80 端口
docker-compose run -p 5002:80 vote

三、实战技巧与避坑指南

1. 配置文件优化

  • 使用 .env 文件存储敏感信息:将数据库密码、API 密钥等写在 .env 文件中,在 docker-compose.yml 中用 ${变量名} 引用,避免硬编码(如 POSTGRES_PASSWORD=${DB_PWD});
  • 拆分配置文件:复杂项目可拆分多个配置文件(如 base.yml 存基础配置,dev.yml 存开发环境配置),用 -f 组合使用(docker-compose -f base.yml -f dev.yml up -d);
  • 指定镜像标签:避免使用 latest 标签(镜像更新可能导致兼容性问题),明确指定版本(如 redis:7.2-alpine)。

2. 常见问题与解决方案

问题现象原因分析解决方案
up 时提示 “端口被占用”(port is already allocated)主机端口已被其他进程(或旧容器)占用1. 用 netstat -tulpn | grep 端口号查找占用进程,停止该进程;
2. 修改 docker-compose.yml 中的 ports 映射(如将 5000:80 改为 5002:80);
3. 执行 docker-compose down 清理旧容器残留。
服务启动后无法通信(如 vote 连不上 redis)1. 未加入同一网络;
2. 用 IP 访问而非服务名;
3. 服务未就绪(depends_on 仅保证启动顺序)
1. 确认两个服务在 networks 中配置了同一网络(如均加入 frontend);
2. 容器内用服务名访问(如 redis:6379,而非 192.168.0.10:6379);
3. 给服务添加 “健康检查”(healthcheck 字段),确保服务就绪后再通信。
数据卷挂载后数据丢失(容器删除后数据不见)1. 用了 “绑定挂载”(本地目录未持久化);
2. 误执行 docker-compose down -v 删除了命名卷
1. 优先使用 “命名卷”(如 db-data:/path),而非绑定挂载(./local-dir:/path);
2. 避免随意使用 docker-compose down -v,删除卷前确认数据已备份;
3. 用 docker volume ls 查看卷列表,docker volume inspect 卷名 确认数据存储路径。
exec 进入容器提示 “no container found”服务未启动,或容器已停止1. 用 docker-compose ps 确认服务状态(需为 Up);
2. 执行 docker-compose start 服务名 启动容器后再进入。
—scale 扩展后端口冲突(多副本映射同一主机端口)多副本同时映射 “主机端口:容器端口”(如 5000:80),主机端口无法重复绑定1. 仅保留一个副本的 ports 映射,其他副本不暴露主机端口(内部通信用服务名);2. 使用 “动态端口映射”(如 5000-5005:80),让 Compose 自动分配主机端口;3. 生产环境建议用反向代理(如 Nginx)统一入口,避免直接暴露容器端口。

3. 进阶实战技巧

(1)添加健康检查:确保服务就绪后再通信

depends_on 仅能保证 “容器启动顺序”,但无法确保 “服务已就绪”(如数据库容器启动后,需 30 秒才能接受连接)。此时需添加 healthcheck 字段,让 Compose 等待服务就绪后再继续。

示例:给 db 服务添加 PostgreSQL 健康检查:

services:
  db:
    image: postgres:9.4
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - backend
    # 健康检查配置:每 10 秒检查一次,超时 5 秒,3 次成功视为就绪,3 次失败视为不健康
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"] # PostgreSQL 就绪检查命令
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 30s # 服务启动后,等待 30 秒再开始检查(避免启动中误判)
  # vote 服务依赖 db,且仅在 db 健康后才启动
  vote:
    depends_on:
      db:
        condition: service_healthy # 依赖条件:db 服务健康(而非仅启动)
    # 其他配置...

(2)使用 .env 文件管理环境变量

将敏感信息(如数据库密码、API 密钥)写在 .env 文件中,避免硬编码到 docker-compose.yml,便于版本控制和环境切换。

步骤:

  1. 在 docker-compose.yml 同目录创建 .env 文件:
# .env 文件内容(键值对格式,无引号)
DB_PWD=my_secure_password
DB_NAME=voting_db
REDIS_PORT=6379
  1. 在 docker-compose.yml 中引用变量(用 ${变量名}):
services:
  db:
    image: postgres:9.4
    environment:
      - POSTGRES_PASSWORD=${DB_PWD} # 引用 .env 中的 DB_PWD
      - POSTGRES_DB=${DB_NAME} # 引用 .env 中的 DB_NAME
  redis:
    image: redis:alpine
    ports:
      - "${REDIS_PORT}:6379" # 引用 .env 中的 REDIS_PORT
  1. 执行命令时,Compose 会自动加载 .env 文件:
docker-compose up -d  # 无需额外参数,自动读取 .env 变量

(3)批量操作:结合脚本简化重复任务

日常运维中,可编写 Shell 脚本批量执行 Compose 命令,提升效率。例如 “一键部署 + 日志查看 + 状态检查” 脚本:

创建 deploy.sh 文件:

#!/bin/bash
# 一键部署投票应用的脚本

# 1. 定义变量(配置文件路径、项目名)
COMPOSE_FILE="./docker-compose.yml"
PROJECT_NAME="voting-app"

# 2. 停止旧服务
echo "=== 停止旧服务 ==="
docker-compose -f $COMPOSE_FILE -p $PROJECT_NAME down -v

# 3. 拉取最新镜像
echo "=== 拉取最新镜像 ==="
docker-compose -f $COMPOSE_FILE -p $PROJECT_NAME pull

# 4. 启动新服务
echo "=== 启动新服务 ==="
docker-compose -f $COMPOSE_FILE -p $PROJECT_NAME up -d --scale vote=3

# 5. 查看服务状态
echo "=== 服务状态 ==="
docker-compose -f $COMPOSE_FILE -p $PROJECT_NAME ps

# 6. 跟踪 vote 服务日志
echo "=== 实时日志(按 Ctrl+C 退出) ==="
docker-compose -f $COMPOSE_FILE -p $PROJECT_NAME logs -f vote

赋予执行权限并运行:

chmod +x deploy.sh
./deploy.sh

四、总结:Docker Compose 核心工作流

掌握以下 “标准工作流”,即可应对 90% 以上的多容器应用管理场景:

  1. 编写配置文件:根据应用架构,编写 docker-compose.yml(定义服务、网络、数据卷);
  2. 启动服务:docker-compose up -d(后台启动,首次启动自动拉取镜像);
  3. 日常运维:
    • 查看状态:docker-compose ps;
    • 查看日志:docker-compose logs -f 服务名;
    • 进入容器:docker-compose exec 服务名 bash;
    • 重启服务:docker-compose restart 服务名;
  4. 更新应用:
    • 修改配置文件或镜像版本;
    • 执行 docker-compose up -d(Compose 会自动更新变化的服务,不影响其他服务);
  5. 清理资源:
    • 临时停止:docker-compose stop;
    • 彻底清理(含容器、网络):docker-compose down;
    • 清理数据卷(谨慎):docker-compose down -v。

Docker Compose 是 Docker 单机环境的 “编排利器”,尤其适合开发、测试环境和中小型应用的部署。若需管理多主机容器(如分布式应用),可进一步学习 Docker Swarm 或 Kubernetes,但 Compose 作为基础,是掌握容器编排的重要第一步。

建议结合实际项目练习(如用 Compose 部署 “Nginx+MySQL+Node.js” 应用),在实践中熟悉命令和配置细节,遇到问题时参考官方文档(Docker Compose 官方文档)或本文的避坑指南,逐步提升容器管理能力。