Docker Compose 命令指南:构建与管理多容器应用的利器
在现代软件开发和部署中,容器化已成为主流。Docker 提供了一种标准化的方式来打包应用及其依赖,确保在任何环境中都能一致运行。然而,真实世界的应用往往不是单一容器,而是由多个相互协作的服务组成的(例如,Web 服务器、应用后端、数据库、消息队列等)。手动管理这些容器、它们的网络连接、卷和配置会变得异常繁琐。
这时,Docker Compose 应运而生。Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过一个 YAML 文件(通常命名为 docker-compose.yml),你可以声明式地配置你的应用服务,然后使用一个简单的命令来创建和启动所有服务。它极大地简化了复杂应用的开发、测试、暂存和生产环境的部署流程。
本文将作为一份详尽的 Docker Compose 命令指南,深入探讨其核心命令、常用选项以及实际应用场景,帮助你更高效地构建和管理你的多容器应用。
1. 前言:docker-compose.yml 文件的重要性
在深入命令之前,理解 docker-compose.yml 文件是至关重要的。它是 Docker Compose 的核心,定义了应用程序的所有服务、网络和卷。每个服务都基于一个 Docker 镜像(可以是一个已存在的镜像,也可以通过 build 指令从 Dockerfile 构建),并可以配置端口映射、卷挂载、环境变量、依赖关系等。
Docker Compose 命令的作用,就是读取这个 YAML 文件,并根据其中的定义来执行相应的操作,例如构建镜像、创建容器、启动、停止、删除服务等。所有的命令几乎都围绕着这个配置文件展开。
默认情况下,Docker Compose 会查找当前目录下的 docker-compose.yml 或 docker-compose.yaml 文件。你也可以使用 -f 选项指定其他文件或多个文件。
2. 安装 Docker Compose
在开始使用命令之前,请确保你已经安装了 Docker 和 Docker Compose。Docker Compose 的安装方式因操作系统而异,可以参考 Docker 官方文档进行安装。通常,它作为一个独立的可执行文件或作为 Docker Desktop 的一部分提供。
安装完成后,你可以在终端运行以下命令检查版本:
bash
docker-compose --version
3. 核心命令详解
3.1 docker-compose up:构建、创建并启动服务
up 命令是 Docker Compose 中最常用、功能最强大的命令。它负责根据 docker-compose.yml 文件定义的内容,执行以下一个或多个操作:
- 构建镜像 (如果需要):如果服务配置使用了
build指令,up命令会先查找本地是否有匹配的镜像。如果没有,或者使用了--build选项,它会根据 Dockerfile 构建新的镜像。 - 创建网络和卷 (如果需要):根据配置文件中定义的网络和卷,创建它们(如果尚不存在)。
- 创建容器 (如果需要):根据服务定义,创建对应的容器实例。如果容器已存在且配置没有变化,Compose 可能会选择跳过创建步骤。
- 启动容器:启动已创建的服务容器。
基本语法:
bash
docker-compose up [options] [service...]
如果不指定 service 名称,它会启动 docker-compose.yml 文件中定义的所有服务。如果指定了服务名称,它只会启动这些服务及其依赖的服务。
常用选项:
-d, --detach: 在后台运行容器,不占用当前终端。这是生产环境或需要同时执行其他操作时最常用的选项。--build: 强制重新构建服务使用的镜像,即使镜像已经存在且没有配置变化。在 Dockerfile 或构建上下文有修改时很有用。--force-recreate: 强制重新创建容器,即使容器已存在且配置没有变化。这会先停止并删除现有容器,再创建新的。--no-deps: 不启动服务所依赖的其他服务。慎用此选项,可能会导致依赖服务无法启动。--no-start: 创建容器但不启动它们。通常与docker-compose start结合使用。--abort-on-container-exit: 如果任何一个容器停止运行,则停止所有容器。对于调试很有用。-V, --renew-anon-volumes: 重新创建匿名卷而不是从之前运行中恢复数据。-t, --timeout <timeout>: 停止容器时的超时时间(以秒为单位,默认为 10)。
示例:
- 启动所有服务并在前台显示日志:
bash
docker-compose up - 在后台启动所有服务:
bash
docker-compose up -d - 强制重新构建
web服务镜像并启动该服务(及其依赖):
bash
docker-compose up --build web - 强制重新创建所有服务并启动:
bash
docker-compose up --force-recreate -d - 启动服务但只创建容器,不启动它们:
bash
docker-compose up --no-start
注意事项:
up命令会根据依赖关系启动服务。例如,如果web服务依赖于db服务,up命令会先启动db,然后启动web。- 在前台模式下 (
-d选项未指定),你可以按下Ctrl+C来优雅地停止服务。
3.2 docker-compose down:停止并移除服务
down 命令是 up 命令的反向操作。它会停止并移除 docker-compose.yml 文件中定义的所有服务、默认网络和自定义网络(如果它们没有被其他容器使用)。
基本语法:
bash
docker-compose down [options]
常用选项:
-v, --volumes: 移除docker-compose.yml文件中定义的匿名卷和指定了driver的命名卷。请注意,默认情况下,没有指定driver的命名卷(即由 Compose 隐式创建或引用的外部命名卷)不会被移除,以防止数据丢失。使用此选项时要小心,特别是对于包含重要数据的卷。--rmi <type>: 移除服务使用的镜像。<type>可以是all(移除所有镜像,包括中间层) 或local(只移除构建过程中生成的本地镜像)。--remove-orphans: 移除不再在docker-compose.yml文件中定义但仍属于该项目的容器。这在使用 Compose 文件进行服务迭代时非常有用,可以清理旧的、未使用的容器。-t, --timeout <timeout>: 停止容器时的超时时间(以秒为单位,默认为 10)。
示例:
- 停止并移除所有服务和默认网络:
bash
docker-compose down - 停止、移除所有服务、网络,并移除匿名卷和指定了 driver 的命名卷:
bash
docker-compose down -v - 停止、移除所有服务、网络,并移除构建生成的本地镜像:
bash
docker-compose down --rmi local - 停止、移除所有服务、网络,并移除孤儿容器:
bash
docker-compose down --remove-orphans
注意事项:
down命令是清理 Compose 项目资源的推荐方式。- 不带
-v选项时,命名卷通常会被保留,这对于需要持久化数据的数据库等服务非常重要。
3.3 docker-compose ps:列出服务容器
ps 命令用于列出当前 Compose 项目中的服务容器及其状态。
基本语法:
bash
docker-compose ps [options] [service...]
如果不指定 service 名称,它会列出所有服务的状态。
常用选项:
-q, --quiet: 只显示容器的 ID。--services: 只显示服务名称。-a, --all: 显示所有容器,包括已停止的。
示例:
- 列出所有服务的状态:
bash
docker-compose ps - 只显示
web服务的容器 ID:
bash
docker-compose ps -q web - 显示所有容器(包括停止的)的状态:
bash
docker-compose ps -a
3.4 docker-compose logs:查看服务日志
logs 命令用于查看服务容器的输出日志。
基本语法:
bash
docker-compose logs [options] [service...]
如果不指定 service 名称,它会聚合并显示所有服务的日志。
常用选项:
-f, --follow: 持续跟踪日志输出(类似于tail -f)。--no-follow: 不持续跟踪日志输出(默认行为)。--tail <number>: 显示日志的最后 N 行。可以指定一个数字,或者all来显示所有日志。-t, --timestamps: 显示日志的时间戳。--no-color: 不使用颜色输出日志。
示例:
- 查看所有服务的历史日志:
bash
docker-compose logs - 持续跟踪
web服务的日志:
bash
docker-compose logs -f web - 查看
db服务的最后 50 行日志:
bash
docker-compose logs --tail 50 db - 查看所有服务的日志并显示时间戳:
bash
docker-compose logs -t
3.5 docker-compose exec:在运行的容器中执行命令
exec 命令用于在指定服务的正在运行的容器中执行任意命令。这对于调试、运行一次性脚本或进入容器的 shell 环境非常有用。
基本语法:
bash
docker-compose exec [options] service command [args...]
必须指定一个服务名称和要在该容器中执行的命令。
常用选项:
-d, --detach: 在后台执行命令,不占用当前终端。-u, --user <user>: 以指定用户身份执行命令。-w, --workdir <path>: 在指定目录中执行命令。-e, --env <VAR=VAL>: 设置环境变量。-T: 禁用伪终端分配。当执行非交互式命令时很有用,可以避免终端相关的错误。
示例:
- 在
web服务容器中执行ls -l命令:
bash
docker-compose exec web ls -l - 进入
app服务容器的 bash shell(交互式):
bash
docker-compose exec app bash - 以 root 用户身份在
db服务容器中执行ps aux:
bash
docker-compose exec -u root db ps aux - 在后台执行一个耗时脚本:
bash
docker-compose exec -d worker /app/scripts/process_queue.sh
exec vs run 注意事项:
exec需要容器已经处于运行状态。run会根据服务配置创建一个新的一次性容器来执行命令,执行完毕后通常会删除容器(使用--rm选项)。run更适合运行数据库迁移、种子数据填充等一次性管理任务。exec更适合在现有、正在运行的容器中进行检查或调试。
3.6 docker-compose build:构建服务镜像
build 命令用于根据 docker-compose.yml 文件中定义了 build 指令的服务来构建镜像。通常,docker-compose up 在需要时会自动执行构建,但你也可以单独使用 build 命令来预先构建镜像或只构建特定服务。
基本语法:
bash
docker-compose build [options] [service...]
如果不指定 service 名称,它会构建所有定义了 build 指令的服务镜像。
常用选项:
--force-rm: 构建过程中强制移除中间容器。--no-cache: 构建镜像时不使用缓存。--pull: 在构建之前总是尝试拉取新版本的 Docker 镜像作为基础镜像。-m, --memory <memory>: 为构建容器分配内存。--parallel: 并行构建多个服务镜像。--progress <type>: 设置构建进度的输出类型 (auto, plain, tty)。
示例:
- 构建所有定义了
build指令的服务镜像:
bash
docker-compose build - 强制重建
web服务镜像,不使用缓存:
bash
docker-compose build --no-cache web - 在构建前拉取新的基础镜像:
bash
docker-compose build --pull
3.7 docker-compose start/stop/restart:控制运行中的服务
这些命令用于控制已经创建但可能处于停止状态(start)或正在运行状态(stop, restart)的服务容器。
基本语法:
bash
docker-compose start [service...]
docker-compose stop [options] [service...]
docker-compose restart [options] [service...]
如果不指定 service 名称,它们会作用于当前项目的所有服务。
常用选项 (stop/restart):
-t, --timeout <timeout>: 停止容器时的超时时间(以秒为单位,默认为 10)。
示例:
- 启动所有已创建但停止的服务:
bash
docker-compose start - 停止
web和worker服务:
bash
docker-compose stop web worker - 重启所有服务:
bash
docker-compose restart - 强制在 5 秒内停止
db服务:
bash
docker-compose stop -t 5 db
3.8 docker-compose rm:移除停止的服务容器
rm 命令用于移除已停止的服务容器。默认情况下,它会提示确认。
基本语法:
bash
docker-compose rm [options] [service...]
如果不指定 service 名称,它会尝试移除所有已停止的服务容器。
常用选项:
-f, --force: 强制移除,不提示确认。-v: 移除与容器关联的匿名卷。
示例:
- 移除所有已停止的服务容器 (会提示确认):
bash
docker-compose rm - 强制移除已停止的
web服务容器:
bash
docker-compose rm -f web - 强制移除所有已停止的服务容器及其匿名卷:
bash
docker-compose rm -fv
注意事项:
rm命令只能移除已停止的容器。要停止并移除,通常先使用stop或down。docker-compose down通常是清理项目的更便捷方式,因为它会先停止服务再移除。
3.9 docker-compose config:验证和查看配置
config 命令用于验证 docker-compose.yml 文件的语法是否正确,并显示最终合并后的配置(特别是当你使用多个 Compose 文件或环境变量时)。它不会实际创建或启动任何资源。
基本语法:
bash
docker-compose config [options]
常用选项:
-q, --quiet: 只检查配置的有效性,不输出具体配置。如果配置有效,返回状态码 0;否则返回非零。-s, --services: 只显示服务名称。-p, --profiles: 显示在配置中定义的 profile 名称。--volumes: 只显示卷名称。--network-names: 只显示网络名称。--hash *: 打印配置的 hash 值。用于检测配置是否发生变化。--format <format>: 输出格式 (json, yaml)。
示例:
- 验证当前目录下的
docker-compose.yml文件语法:
bash
docker-compose config - 验证语法,不输出具体配置 (用于脚本中):
bash
docker-compose config -q - 显示最终合并后的配置 (包括环境变量等):
bash
docker-compose config - 只显示服务名称:
bash
docker-compose config -s
3.10 docker-compose run:运行一次性命令
run 命令用于在指定服务的新建容器中运行一个命令。与 exec 不同,run 会根据服务定义(包括端口映射、卷挂载、依赖关系等)创建一个新的容器来执行命令,执行完毕后,这个容器通常会退出。这非常适合运行一次性的任务,如数据库迁移、数据备份、执行测试脚本等。
基本语法:
bash
docker-compose run [options] [-v VOLUME...] [-p PORT...] [-e VAR=VAL...] service command [args...]
必须指定一个服务名称和要在该容器中执行的命令。
常用选项:
-d, --detach: 在后台运行命令。--name <name>: 为运行命令的容器指定一个自定义名称。--rm: 命令执行完毕后自动移除容器。这是最常用的选项,用于清理一次性任务产生的容器。-e, --env <VAR=VAL>: 设置环境变量。-v, --volume <host-path:container-path>: 挂载一个卷。-p, --publish <host-port:container-port>: 映射端口。-u, --user <user>: 以指定用户身份执行命令。-w, --workdir <path>: 在指定目录中执行命令。--service-ports: 运行容器时映射服务定义中指定的端口。默认情况下run不映射端口。--use-aliases: 允许容器访问服务的网络别名。
示例:
- 在
app服务的新容器中运行数据库迁移脚本,并在完成后移除容器:
bash
docker-compose run --rm app python manage.py migrate - 在
db服务的新容器中备份数据库,并将备份文件挂载到本地目录:
bash
docker-compose run --rm -v $(pwd)/backup:/backup db pg_dump mydatabase > /backup/db_backup.sql - 在
web服务的新容器中启动一个临时 shell 并映射端口,以便进行调试:
bash
docker-compose run --rm --service-ports web bash
run vs exec 总结:
run: 创建新容器,执行命令后通常移除。用于一次性任务。可以配置端口、卷等。exec: 在已运行容器中执行命令。用于调试、进入运行环境。
4. 其他常用命令
4.1 docker-compose pull:拉取服务镜像
pull 命令用于拉取 docker-compose.yml 文件中指定的镜像(那些使用 image 指令的服务)。
基本语法:
bash
docker-compose pull [options] [service...]
如果不指定 service 名称,它会拉取所有使用 image 指令的服务镜像。
常用选项:
--ignore-pull-failures: 即使拉取失败也继续拉取其他服务镜像。--no-parallel: 禁用并行拉取。
示例:
- 拉取所有服务使用的镜像:
bash
docker-compose pull - 拉取
web和worker服务的新镜像:
bash
docker-compose pull web worker
4.2 docker-compose push:推送服务镜像
push 命令用于推送服务使用的镜像。通常只用于使用 build 指令构建并希望推送到 Docker Registry 的自定义镜像。
基本语法:
bash
docker-compose push [options] [service...]
示例:
- 推送
web和app服务构建的镜像到 Registry:
bash
docker-compose push web app
4.3 docker-compose images:列出项目中使用的镜像
images 命令列出当前 Compose 项目中各个服务正在使用或将要使用的镜像。
基本语法:
bash
docker-compose images [options] [service...]
常用选项:
-q, --quiet: 只显示镜像 ID。
示例:
- 列出所有服务使用的镜像:
bash
docker-compose images
4.4 docker-compose top:显示服务容器的进程
top 命令用于显示服务容器中正在运行的进程列表,类似于 docker top 命令。
基本语法:
bash
docker-compose top [service...]
如果不指定 service 名称,它会显示所有服务容器的进程。
示例:
- 显示
web服务容器的进程列表:
bash
docker-compose top web
4.5 docker-compose events:监听容器事件
events 命令会监听并打印 Compose 项目中容器发出的事件。
基本语法:
bash
docker-compose events [options] [service...]
示例:
- 监听所有服务容器事件:
bash
docker-compose events
4.6 docker-compose version:显示版本信息
version 命令显示 Docker Compose、Docker Engine、Compose File 格式的版本信息。
基本语法:
bash
docker-compose version [options]
常用选项:
--short: 只显示版本号。
示例:
bash
docker-compose version
5. 高级用法和相关概念
理解 Docker Compose 命令的同时,还需要掌握一些相关的概念和高级用法:
- 项目名称 (
-p, --project-name): Docker Compose 会为每个项目分配一个名称,默认是当前目录名。这个名称会作为容器、网络和卷名称的前缀,用于隔离不同的 Compose 项目。可以使用-p选项指定项目名称,或设置COMPOSE_PROJECT_NAME环境变量。
bash
docker-compose -p myapp up -d - 指定 Compose 文件 (
-f, --file): 可以使用-f选项指定一个或多个 Compose 文件。当指定多个文件时,Compose 会将它们合并,后面的文件会覆盖前面的文件中的相同配置。这对于管理特定环境(如开发、生产)或功能的配置非常有用。
bash
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up - 环境变量: Compose 文件支持使用环境变量,这使得配置更加灵活。例如
${POSTGRES_VERSION}。你可以通过 Shell 环境变量或.env文件来设置这些变量。 - Profiles (
--profile): Compose V2 引入了 Profiles 的概念,允许你在 Compose 文件中定义不同的服务组,然后在运行时只激活特定的组。这对于管理大型、包含多种可选组件的应用非常有用。
yaml
# docker-compose.yml
services:
app: ...
db: ...
worker:
profiles: ["background"] # 只在 profile 'background' 被激活时启动
celery-monitor:
profiles: ["monitor"] # 只在 profile 'monitor' 被激活时启动
bash
# 启动 app 和 db (默认 profile)
docker-compose up -d
# 启动 app, db, 和 worker
docker-compose --profile background up -d
# 启动 app, db, worker, 和 celery-monitor
docker-compose --profile background --profile monitor up -d extends关键字: 允许一个 Compose 文件基于另一个 Compose 文件或服务定义进行扩展,实现配置的复用。
6. 最佳实践
- 使用版本控制: 将
docker-compose.yml文件和相关的 Dockerfile、应用代码一起放入版本控制系统 (如 Git),以便跟踪变化和协作。 - 定义明确的服务名称: 使用具有描述性的服务名称 (如
web,api,db,redis,worker)。 - 管理敏感数据: 不要将密码、API 密钥等敏感信息直接写入 Compose 文件。使用环境变量、Docker Secrets 或 Docker Compose 的配置(Configs)功能来管理。
- 利用
.env文件: 使用.env文件来存储环境变量,Docker Compose 会自动加载它,使得配置更易于管理。 - 模块化配置: 对于复杂的应用,考虑使用多个 Compose 文件 (
-f选项) 或extends关键字来组织和复用配置。 - 使用 Profiles: 利用 Profiles 按功能或环境组织服务,减少主 Compose 文件的复杂性,并提供灵活的部署选项。
- 理解
up,down,start,stop,restart,run,exec的区别: 选择正确的命令执行任务,避免混淆,特别是在处理持久化数据和一次性任务时。 - 定期清理: 使用
docker-compose down或docker system prune来清理不再使用的容器、网络、卷和镜像,释放磁盘空间。
7. 结语
Docker Compose 是一个强大且易于使用的工具,它将多容器应用的定义和生命周期管理从复杂的命令行操作简化为对一个声明式 YAML 文件的操作和几个简单的命令。掌握 up, down, ps, logs, exec, run, build, config 等核心命令及其选项,将显著提高你在构建、测试和部署复杂应用时的效率。
通过本文的详细指南,你应该对 Docker Compose 的主要命令有了深入的了解。记住,最好的学习方式是实践。创建一个简单的多容器应用 (web + db) 的 docker-compose.yml 文件,然后反复使用这些命令来启动、停止、检查、修改和清理你的应用。随着你对 Compose 的熟悉,你将能够轻松驾驭更复杂的容器化应用场景。