🔍搜索⌘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 命令实战(按使用频率排序)

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 官方文档)或这篇的避坑指南,慢慢就顺手了。