Docker Compose 命令使用教程:构建与管理多容器应用的全攻略
Docker Compose 是 Docker 官方提供的一个工具,用于定义和运行多容器的 Docker 应用程序。通过一个简单的 YAML 文件 (docker-compose.yml
),你可以配置应用的服务、网络、卷等,然后使用单个命令启动、停止、重建和管理整个应用程序栈。
本文将带你深入了解 Docker Compose 的核心概念,详细解析其常用命令及其用法,并通过实际示例帮助你掌握如何高效地构建和管理复杂的容器化应用。
目录
- Docker Compose 简介
- 为什么使用 Docker Compose?
- 核心概念:服务、网络、卷
- 安装 Docker Compose
- 检查安装
docker-compose.yml
文件:Compose 的灵魂- 文件结构概览 (version, services, networks, volumes)
- 定义一个简单的服务 (image, ports, volumes, environment)
- 多服务示例:Web 应用与数据库
- 依赖管理 (
depends_on
) - 网络和卷的配置
- 核心 Docker Compose 命令详解
docker-compose up
: 启动你的应用- 常用选项:
-d
,--build
,--force-recreate
,--no-deps
- 常用选项:
docker-compose down
: 停止和移除容器- 常用选项:
--volumes
,--rmi
,--remove-orphans
- 常用选项:
docker-compose ps
: 查看服务状态docker-compose logs
: 查看容器日志- 常用选项:
-f
,--tail
- 常用选项:
docker-compose exec
: 在运行中的容器中执行命令docker-compose build
: 构建服务镜像- 常用选项:
--no-cache
,--force-rm
- 常用选项:
docker-compose restart
: 重启服务docker-compose stop
: 停止服务docker-compose start
: 启动已停止的服务docker-compose rm
: 移除停止的容器- 常用选项:
-f
,-v
- 常用选项:
- 进阶 Docker Compose 使用技巧
- 使用多个 Compose 文件 (
-f
选项) - 使用环境变量 (
.env
文件) - 扩展和覆盖服务配置
- 服务伸缩 (
docker-compose scale
) - 自定义网络和卷
- 健康检查 (
healthcheck
) - 调试与排错 (
--verbose
,config
)
- 使用多个 Compose 文件 (
- 完整示例:一个博客平台的 Compose 配置与管理
docker-compose.yml
文件分析- 启动、管理、停止过程演示
- Docker Compose 最佳实践
- 总结
1. Docker Compose 简介
在微服务或哪怕是一个稍微复杂的单体应用中,通常不止一个进程。例如,一个 Web 应用可能需要一个 Web 服务器、一个应用服务器、一个数据库,可能还需要缓存、消息队列等等。如果手动地运行每一个容器,并且正确地连接它们、设置环境变量、挂载卷,这将是一项繁琐且容易出错的任务。
Docker Compose 应运而生,它解决了这个问题。它允许你使用一个声明式的配置文件(默认是 docker-compose.yml
)来定义应用程序的所有服务、它们之间的依赖关系、网络设置、卷挂载等等。然后,你只需要执行一个命令,Docker Compose 就会按照配置文件描述的方式,创建并启动所有需要的容器、设置网络、挂载卷。
为什么使用 Docker Compose?
- 简化配置: 将复杂的 Docker 命令和配置抽象到 YAML 文件中,一目了然。
- 易于管理: 使用单个命令管理整个应用栈的生命周期(启动、停止、重启、删除)。
- 环境隔离: 默认情况下,Compose 会为项目创建一个独立的网络,确保服务之间的隔离。
- 可重复性: 相同的
docker-compose.yml
文件可以在任何安装了 Docker 和 Docker Compose 的环境中重复部署相同的应用环境。 - 提高效率: 特别适用于开发、测试和持续集成环境,可以快速搭建和销毁复杂的应用环境。
核心概念:服务、网络、卷
在 docker-compose.yml
文件中,有几个核心概念需要理解:
- Service (服务): 一个服务代表应用中的一个容器或一组功能相同的容器。例如,一个 Web 服务,一个数据库服务。每个服务都由一个 Docker 镜像定义(可以是 Dockerfile 构建的镜像,也可以是 Docker Hub 或其他仓库的镜像)。你可以为服务指定运行参数,如端口映射、卷挂载、环境变量、依赖等。
- Network (网络): Compose 会为项目自动创建一个默认的网络,所有服务都会加入到这个网络中,并可以通过服务名相互访问(服务发现)。你也可以自定义网络,以实现更复杂的网络拓扑或与外部网络集成。
- Volume (卷): 用于持久化存储数据。容器是短暂的,其内部数据会随容器的删除而丢失。卷可以将数据存储在宿主机上,与容器的生命周期分离,确保数据不会丢失。Compose 允许你定义和管理卷。
2. 安装 Docker Compose
现代的 Docker Desktop 版本(适用于 Windows 和 macOS)通常已经包含了 Docker Compose。对于 Linux 系统,你需要单独安装。
检查是否已安装:
打开终端或命令行,运行以下命令:
“`bash
docker compose version
或者对于旧版本:
docker-compose version
“`
如果你看到版本信息,说明 Compose 已经安装并可用。
Linux 手动安装 (以 v2.24.6 为例,请根据实际最新版本调整):
-
下载最新版本的 Compose 可执行文件:
“`bash
COMPOSE_VERSION=v2.24.6 # 替换为最新版本号
DEST=/usr/local/bin/docker-compose # 或者其他你希望安装的位置curl -L https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m) -o ${DEST}
2. 给予执行权限:
bash
chmod +x ${DEST}
3. 验证安装:
bash
docker-compose version
“`
注意: Docker Compose V2 是推荐使用的版本,它作为 docker
CLI 的一个子命令集成,使用 docker compose
而不是 docker-compose
。新项目和新安装应优先使用 V2。本文中的命令示例将同时展示 docker compose
和 docker-compose
(legacy) 形式,但推荐使用前者。
3. docker-compose.yml
文件:Compose 的灵魂
docker-compose.yml
是 Compose 的核心配置文件,采用 YAML 格式。它描述了组成应用程序的所有服务、网络和卷。
文件结构概览
一个典型的 docker-compose.yml
文件结构如下:
“`yaml
version: ‘3.8’ # 指定 Compose 文件格式版本
services:
service_name_1: # 服务名称
# 服务配置,如 image, ports, volumes, environment 等
…
service_name_2: # 另一个服务
# 服务配置
…
networks: # 可选:自定义网络配置
network_name_1:
# 网络配置
…
volumes: # 可选:自定义卷配置
volume_name_1:
# 卷配置
…
“`
version
: 指定 Compose 文件格式的版本,这会影响支持的配置选项。通常使用较新的版本,如 ‘3.8’ 或更高。services
: 这是最关键的部分,列出组成应用程序的所有服务。每个顶级键都是一个服务名称。networks
和volumes
: 可选部分,用于定义自定义网络和卷,以便在多个服务之间共享或进行更精细的控制。
定义一个简单的服务
让我们看一个定义单个 Nginx Web 服务器服务的例子:
“`yaml
docker-compose.yml
version: ‘3.8’
services:
web: # 服务名称
image: nginx:latest # 使用 nginx:latest 镜像
ports:
– “80:80” # 将宿主机的 80 端口映射到容器的 80 端口
volumes:
– ./html:/usr/share/nginx/html # 将当前目录下的 html 文件夹作为卷挂载到容器的 Nginx 默认网页目录
environment: # 设置环境变量
– NGINX_HOST=example.com
– NGINX_PORT=80
“`
解释:
web
: 这是服务的名称。在 Compose 网络中,其他服务可以通过web
这个名字访问到这个容器。image: nginx:latest
: 指定服务使用的 Docker 镜像。Compose 会尝试拉取nginx:latest
镜像。ports: - "80:80"
: 配置端口映射。格式是宿主机端口:容器端口
。这里将宿主机的 80 端口映射到容器内部 Nginx 运行的 80 端口。volumes: - ./html:/usr/share/nginx/html
: 配置卷挂载。格式是宿主机路径或卷名称:容器路径
。这将宿主机当前目录下的html
文件夹(如果不存在会自动创建)挂载到容器内的/usr/share/nginx/html
路径。这意味着你可以直接修改宿主机的html
文件夹内容,容器内的 Nginx 会立即加载更新。environment
: 设置传递给容器的环境变量。
多服务示例:Web 应用与数据库
一个更常见的场景是 Web 应用连接数据库。比如一个简单的 Python Flask 应用连接 PostgreSQL 数据库:
“`yaml
docker-compose.yml
version: ‘3.8’
services:
web:
build: . # 指定使用当前目录的 Dockerfile 构建镜像
ports:
– “5000:5000”
volumes:
– .:/app # 将当前目录挂载到容器的 /app 目录 (用于开发时代码同步)
environment:
DATABASE_URL: postgres://user:password@db:5432/mydatabase
depends_on:
– db # web 服务依赖于 db 服务,db 会先启动
db:
image: postgres:13 # 使用 PostgreSQL 13 镜像
environment:
POSTGRES_DB: mydatabase
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
– postgres_data:/var/lib/postgresql/data # 将数据持久化到名为 postgres_data 的卷
volumes: # 顶层 volumes 定义,用于创建命名卷
postgres_data:
“`
解释:
-
web
服务:build: .
: Compose 会在当前目录寻找Dockerfile
并构建一个新的镜像用于此服务。ports: - "5000:5000"
: 映射端口。volumes: - .:/app
: 挂载当前目录到容器的/app
。environment: DATABASE_URL: ...
: 设置数据库连接字符串,注意主机名使用了db
,这是 Compose 网络中db
服务的名称。depends_on: - db
: 声明web
服务依赖于db
服务。Compose 会确保db
容器在web
容器启动之前创建和启动。注意:depends_on
只保证启动顺序,不保证服务的“就绪”状态。对于需要数据库完全启动并接受连接的情况,可能还需要在应用代码中实现重试逻辑,或者使用healthcheck
。
-
db
服务:image: postgres:13
: 使用官方的 PostgreSQL 镜像。environment
: 设置 PostgreSQL 镜像需要的环境变量来初始化数据库、用户和密码。volumes: - postgres_data:/var/lib/postgresql/data
: 将容器内数据库存储目录/var/lib/postgresql/data
挂载到一个名为postgres_data
的命名卷。命名卷由 Docker 管理,推荐用于生产环境的数据持久化。
-
顶层
volumes
: 定义了一个名为postgres_data
的命名卷。当 Compose 第一次运行时,如果该卷不存在,它会自动创建。
依赖管理 (depends_on
)
depends_on
是在 services
部分为某个服务指定的列表。它告诉 Compose 在启动当前服务之前,必须先启动列出的依赖服务。这对于确保服务按正确的顺序启动非常重要,例如数据库必须在应用服务器之前启动。
“`yaml
services:
app:
# … config …
depends_on:
– db
– cache
db:
# … config …
cache:
# … config …
“`
在这个例子中,app
服务将在 db
和 cache
服务启动之后才启动。
网络和卷的配置
默认情况下,Compose 会创建一个默认的 bridge
网络,所有服务都会加入。你也可以在顶层 networks
部分自定义网络:
“`yaml
version: ‘3.8’
services:
web:
image: nginx
networks:
– frontend_network # 加入 frontend_network
app:
image: myapp
networks:
– frontend_network # 加入 frontend_network
– backend_network # 加入 backend_network
db:
image: postgres
networks:
– backend_network # 只加入 backend_network
networks:
frontend_network: # 定义一个自定义网络
driver: bridge
backend_network: # 定义另一个自定义网络
driver: bridge
“`
在这个例子中,web
和 app
可以相互通信,app
和 db
可以相互通信,但 web
和 db
无法直接通信,除非通过 app
中转。这提供了更好的服务隔离。
卷除了使用命名卷外,也可以使用绑定挂载 (bind mounts),上面 Web 示例中的 ./html:/usr/share/nginx/html
就是绑定挂载。绑定挂载通常用于:
- 将源代码挂载到容器进行开发(代码修改后容器内立即生效)。
- 将配置文件挂载到容器。
- 将宿主机的特定目录挂载到容器。
而命名卷(如 postgres_data
)通常用于:
- 持久化数据库数据、日志等重要信息。
- 由 Docker 完全管理其生命周期和位置。
4. 核心 Docker Compose 命令详解
有了 docker-compose.yml
文件,就可以使用 docker compose
(或 docker-compose
) 命令来管理整个应用了。下面是核心命令的详细说明。
docker compose up
: 启动你的应用
这是最常用的命令。它根据 docker-compose.yml
文件配置,构建(如果需要)并启动服务。如果服务容器已经存在,它会尝试停止并重建(如果配置有变化)或直接启动已停止的容器。
基本用法:
bash
docker compose up
这会在前台启动所有服务,并将所有容器的日志输出到终端。按下 Ctrl+C
会停止容器。
常用选项:
-d
(或--detach
): 在后台模式下运行容器。这是生产环境或长时间运行应用常用的方式。
bash
docker compose up -d--build
: 在启动之前强制重新构建服务关联的镜像。即使 Dockerfile 或构建上下文没有变化,也会执行构建过程。
bash
docker compose up -d --build
如果你修改了Dockerfile
或构建上下文中的文件,只需docker compose up -d
,Compose 会检测到变化并自动重建。只有当你需要强制完全重建时才使用--build
。--force-recreate
: 强制重建容器,即使容器的配置(镜像、命令、卷等)没有变化。这对于解决一些状态异常的问题很有用。
bash
docker compose up -d --force-recreate--no-deps
: 不启动服务所依赖的服务。只启动指定的或当前目录下的服务。慎用,可能导致依赖的服务不可用。
bash
docker compose up -d --no-deps web # 只启动 web 服务,不检查其依赖--no-build
: 不构建服务镜像,即使镜像不存在或 Dockerfile 有变化。如果镜像不存在,会报错。
bash
docker compose up --no-build--no-start
: 创建容器但不启动它们。
bash
docker compose up --no-start[service_name...]
: 只启动指定的单个或多个服务及其依赖项。
bash
docker compose up -d web # 启动 web 服务及其依赖 (如 db)
docker compose down
: 停止和移除容器
优雅地停止所有服务,并移除容器、网络和(可选地)卷和镜像。这是清理 Compose 项目的推荐方式。
基本用法:
bash
docker compose down
这会停止并移除 docker-compose.yml
文件中定义的所有容器和服务创建的网络。
常用选项:
--volumes
(或-v
): 移除 Compose 文件中定义的命名卷,以及匿名卷。请谨慎使用此选项,因为它会删除数据。
bash
docker compose down --volumes--rmi type
: 移除服务使用的镜像。type
可以是local
(只移除没有 tag 的镜像) 或all
(移除所有使用的镜像)。
bash
docker compose down --rmi local--remove-orphans
: 移除 Compose 文件中未定义但连接到项目网络的容器。这可能发生在手动运行容器并将其连接到 Compose 项目网络后。
bash
docker compose down --remove-orphans-t seconds
(或--timeout seconds
): 停止容器的超时时间(默认为 10 秒)。
bash
docker compose down -t 30
docker compose ps
: 查看服务状态
列出 Compose 项目中所有服务的容器状态。
基本用法:
bash
docker compose ps
输出通常包括:容器 ID、镜像、命令、创建时间、状态(运行中、已停止、退出等)、端口、服务名称。
NAME IMAGE COMMAND CREATED STATUS PORTS
myproject-web-1 myproject-web "python app.py" 2 minutes ago Up 2 minutes 0.0.0.0:5000->5000/tcp
myproject-db-1 postgres:13 "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 5432/tcp
-q
(或--quiet
): 只显示容器 ID。
bash
docker compose ps -q--services
: 只显示服务名称。
bash
docker compose ps --services-a
(或--all
): 显示所有容器,包括已停止的。
docker compose logs
: 查看容器日志
查看 Compose 项目中所有服务的聚合日志输出,或者指定服务的日志。
基本用法:
bash
docker compose logs
显示所有服务的历史日志。
常用选项:
-f
(或--follow
): 持续输出日志(类似tail -f
)。
bash
docker compose logs -f--tail N
: 只显示每服务末尾的 N 行日志。
bash
docker compose logs --tail 100[service_name...]
: 只显示指定服务的日志。
bash
docker compose logs -f web # 只查看 web 服务的日志--no-log-prefix
: 不显示日志输出前的服务名称和时间戳等前缀信息。
bash
docker compose logs --no-log-prefix web
docker compose exec
: 在运行中的容器中执行命令
在指定服务的运行中容器中执行一个命令。这对于调试或执行一次性任务非常有用。
基本用法:
bash
docker compose exec [options] SERVICE COMMAND [ARGS...]
例如,进入 web
服务容器的 bash 终端(如果容器内有 bash):
bash
docker compose exec web bash
在 db
服务容器中执行 psql 命令连接数据库:
bash
docker compose exec db psql -U user mydatabase
常用选项:
-d
(或--detach
): 在后台执行命令。-e KEY=VALUE
(或--env KEY=VALUE
): 设置环境变量。-u USER
(或--user USER
): 指定执行命令的用户。-w DIR
(或--workdir DIR
): 指定执行命令的工作目录。
docker compose build
: 构建服务镜像
仅构建或重建服务关联的镜像。当你只修改了 Dockerfile
或构建上下文,想先构建镜像而不启动容器时使用。
基本用法:
bash
docker compose build [service_name...]
构建 docker-compose.yml
中所有服务的镜像:
bash
docker compose build
只构建指定服务的镜像:
bash
docker compose build web
常用选项:
--no-cache
: 构建镜像时禁用缓存。强制从头开始构建每一步。
bash
docker compose build --no-cache web--force-rm
: 在构建过程中,即使构建失败,也删除中间容器。--pull
: 总是尝试拉取最新的基础镜像。-q
(或--quiet
): 构建过程中不显示输出。
docker compose restart
: 重启服务
重启 Compose 项目中的服务容器。
基本用法:
bash
docker compose restart [service_name...]
重启所有服务:
bash
docker compose restart
重启指定的 web
服务:
bash
docker compose restart web
-t seconds
(或--timeout seconds
): 停止容器的超时时间,然后启动。
docker compose stop
: 停止服务
停止 Compose 项目中的服务容器,但不会移除它们。停止的容器仍然存在,可以稍后使用 start
命令快速启动。
基本用法:
bash
docker compose stop [service_name...]
停止所有服务:
bash
docker compose stop
停止指定的 web
服务:
bash
docker compose stop web
-t seconds
(或--timeout seconds
): 停止容器的超时时间。
docker compose start
: 启动已停止的服务
启动 Compose 项目中已停止的服务容器。
基本用法:
bash
docker compose start [service_name...]
启动所有已停止的服务:
bash
docker compose start
启动指定的 web
服务:
bash
docker compose start web
docker compose rm
: 移除停止的容器
移除 Compose 项目中已停止的服务容器。运行中的容器不会被移除。
基本用法:
bash
docker compose rm [service_name...]
移除所有已停止的服务容器:
bash
docker compose rm
移除指定的 web
服务已停止的容器:
bash
docker compose rm web
常用选项:
-f
(或--force
): 强制移除运行中的容器(不推荐,最好先 stop)。-v
(或--volumes
): 移除与容器关联的匿名卷。
5. 进阶 Docker Compose 使用技巧
掌握了核心命令,再来看看一些更高级的用法,它们能让你的 Compose 配置更加灵活和强大。
使用多个 Compose 文件 (-f
选项)
你可以使用 -f
选项指定多个 Compose 文件。Compose 会将这些文件按顺序合并。这对于定义基础配置,然后用另一个文件覆盖或扩展它非常有用,例如用于开发、测试和生产环境的不同配置。
示例:
docker-compose.yml
(基础配置):
“`yaml
docker-compose.yml
version: ‘3.8’
services:
web:
image: myapp:latest
ports:
– “80:80”
volumes:
– data:/app/data
db:
image: postgres:13
environment:
POSTGRES_DB: mydatabase
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
data:
“`
docker-compose.dev.yml
(开发环境覆盖,例如挂载源代码、映射更多端口、使用不同的镜像或命令):
“`yaml
docker-compose.dev.yml
version: ‘3.8’
services:
web:
build: . # 开发环境使用构建的镜像,而不是拉取
command: python manage.py runserver 0.0.0.0:8000 # 开发时使用 Flask 开发服务器
ports:
– “8000:8000” # 开发时映射 8000 端口
volumes:
– .:/app # 挂载当前目录的源代码
# data 卷仍然来自基础文件
environment:
DEBUG: “True”
“`
使用方式:
启动开发环境:
bash
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
启动生产环境(只用基础文件):
bash
docker compose up -d
注意,默认文件名是 docker-compose.yml
,所以如果你只用基础文件,可以省略 -f docker-compose.yml
。Compose 会按照指定顺序合并文件,后一个文件中的配置会覆盖前一个文件中的同名配置。
使用环境变量 (.env
文件)
Compose 支持读取 .env
文件中的环境变量,并在 docker-compose.yml
文件中使用它们。这对于管理敏感信息(如密码)或不同环境下的配置(如端口号、镜像标签)非常方便。
在项目根目录创建一个 .env
文件:
“`dotenv
.env
DB_PASSWORD=your_secure_password
APP_PORT=80
IMAGE_TAG=latest
“`
在 docker-compose.yml
中使用环境变量:
“`yaml
docker-compose.yml
version: ‘3.8’
services:
web:
image: myapp:${IMAGE_TAG} # 使用 IMAGE_TAG 变量
ports:
– “${APP_PORT}:80” # 使用 APP_PORT 变量
environment:
DB_PASSWORD: ${DB_PASSWORD} # 将 DB_PASSWORD 变量传递给容器
“`
Compose 在解析 YAML 文件时会自动加载 .env
文件,并将其中的变量替换到 YAML 文件中的 ${VARIABLE}
语法处。
扩展和覆盖服务配置
除了使用多个文件,你也可以在同一个文件中使用 extends
指令来继承和覆盖服务配置,但这在较新的 Compose 版本中已被多文件方式取代,推荐使用多文件方式。多文件方式更灵活。
服务伸缩 (docker compose scale
)
可以增加或减少特定服务的运行容器数量。
基本用法:
“`bash
docker compose scale SERVICE=NUM [SERVICE=NUM…]
或者使用 up 命令的 –scale 选项 (推荐,因为它也会处理依赖和网络等)
docker compose up -d –scale web=3
“`
例如,将 web
服务扩展到 3 个容器:
“`bash
docker compose up -d –scale web=3
或者 (旧方式,不推荐)
docker-compose scale web=3
“`
注意:服务需要是无状态的才能很好地进行伸缩。有状态服务(如数据库)通常不通过这种方式伸缩。Compose 的伸缩功能相对简单,更高级的编排(如自动扩缩容、滚动更新)需要 Docker Swarm 或 Kubernetes 等工具。
自定义网络和卷
除了在 networks
和 volumes
顶层定义,你还可以在服务内部定义匿名卷(如上面的 ./html:/usr/share/nginx/html
,左侧是路径)或在网络中为服务指定别名。
“`yaml
version: ‘3.8’
services:
app:
image: myapp
networks:
backend:
aliases: # 在 backend 网络中,app 服务可以用 app 和 my_app_alias 两个名字访问
– my_app_alias
db:
image: postgres
networks:
– backend # db 服务只加入 backend 网络
networks:
backend:
“`
健康检查 (healthcheck
)
定义如何检测服务容器是否健康。这对于 depends_on
不足以来判断依赖服务是否“就绪”时非常有用。
yaml
services:
db:
image: postgres
# ... 其他配置 ...
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d mydatabase"] # 检查数据库是否准备好接受连接
interval: 5s # 每隔 5 秒检查一次
timeout: 5s # 每次检查的超时时间
retries: 5 # 检查失败重试次数
start_period: 10s # 容器启动后等待 10 秒才开始第一次健康检查
depends_on
可以与 healthcheck
结合使用,例如 depends_on: {db: {condition: service_healthy}}
,这样 web
服务就会等待 db
服务被标记为 healthy
后才启动。
调试与排错
docker compose config
: 验证并显示 Compose 配置的完整解析结果,包括合并了多个文件、替换了环境变量后的内容。这对于调试配置错误非常有帮助。
bash
docker compose config
docker compose -f docker-compose.yml -f docker-compose.dev.yml config--verbose
: 在运行任何 Compose 命令时添加--verbose
选项,可以显示更详细的调试信息,例如执行的 Docker API 调用。
bash
docker compose --verbose up -d- 检查容器日志 (
docker compose logs
) 是排查应用启动或运行问题的首要步骤。 - 使用
docker compose ps -a
查看所有容器(包括退出的),检查其状态和退出码。
6. 完整示例:一个博客平台的 Compose 配置与管理
假设我们有一个简单的博客平台,包含以下组件:
- Web 应用 (基于 Python/Flask)
- API 服务 (基于 Node.js)
- 数据库 (PostgreSQL)
- 缓存 (Redis)
我们来创建一个 docker-compose.yml
文件来定义和管理它们。
“`yaml
docker-compose.yml
version: ‘3.8’
services:
webapp:
build: ./webapp # webapp 目录包含 Dockerfile
ports:
– “80:5000” # 宿主机 80 映射到容器 5000
volumes:
– ./webapp:/app # 挂载源代码
environment:
API_URL: http://api:3000 # 通过服务名访问 API
REDIS_HOST: redis # 通过服务名访问 Redis
DATABASE_URL: postgres://user:password@db:5432/blogdb
depends_on:
– api # 依赖 API
– db # 依赖数据库
– redis # 依赖缓存
api:
build: ./api # api 目录包含 Dockerfile
ports:
– “3000:3000” # 只暴露容器端口 3000,供 webapp 内部访问
volumes:
– ./api:/app # 挂载源代码
environment:
DATABASE_URL: postgres://user:password@db:5432/blogdb
depends_on:
– db # 依赖数据库
healthcheck: # 定义 API 的健康检查
test: [“CMD”, “curl”, “-f”, “http://localhost:3000/health”] # 假设 API 有一个健康检查接口
interval: 10s
timeout: 5s
retries: 3
db:
image: postgres:13
environment:
POSTGRES_DB: blogdb
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
– blog_db_data:/var/lib/postgresql/data # 数据持久化
healthcheck: # 定义数据库的健康检查
test: [“CMD-SHELL”, “pg_isready -U user -d blogdb”]
interval: 5s
timeout: 3s
retries: 5
redis:
image: redis:latest
volumes:
– blog_redis_data:/data # 数据持久化
healthcheck: # 定义 Redis 的健康检查
test: [“CMD”, “redis-cli”, “ping”]
interval: 5s
timeout: 3s
retries: 5
volumes: # 定义命名卷
blog_db_data:
blog_redis_data:
“`
假设你在项目根目录创建了 webapp
和 api
两个子目录,并在其中放好了相应的 Dockerfile
和应用代码。
管理过程演示:
- 构建并启动整个应用:
bash
docker compose up -d --build
Compose 会按照depends_on
的顺序先构建镜像(如果需要),然后启动db
->redis
->api
->webapp
服务。-d
让它们在后台运行。 - 查看服务状态:
bash
docker compose ps
查看所有服务的运行状态、端口映射等。 - 查看日志 (例如 webapp 和 api):
bash
docker compose logs -f webapp api - 进入 api 容器执行命令:
bash
docker compose exec api bash
# 现在你就在 api 容器内部了,可以执行各种 shell 命令
# 例如:curl http://localhost:3000/health
# exit 退出容器 shell - 停止 webapp 服务:
bash
docker compose stop webapp - 启动 webapp 服务:
bash
docker compose start webapp - 重启 api 服务:
bash
docker compose restart api - 伸缩 webapp 服务 (例如增加到 2 个实例):
bash
docker compose up -d --scale webapp=2
再次运行docker compose ps
会看到两个 webapp 容器。 - 停止并清理整个应用 (移除容器、网络和卷):
bash
docker compose down --volumes
这将停止所有服务,移除容器和 Compose 创建的网络,并删除blog_db_data
和blog_redis_data
这两个命名卷(数据会丢失!谨慎使用--volumes
)。
7. Docker Compose 最佳实践
- 使用新版本的 Compose 文件格式: 推荐使用 version ‘3.x’ 或更高版本,它们支持 Swarm 模式(虽然 Compose 主要用于单主机,但语法兼容有助于后续迁移)和更多的配置选项。
- 将构建上下文与 Dockerfile 放在一起: 使用
build: .
或build: ./service_dir
时,确保 Dockerfile 就在指定的目录中。 - 使用命名卷进行数据持久化: 对于数据库、日志等重要数据,优先使用命名卷而不是绑定挂载到随机的宿主机目录,命名卷由 Docker 管理,更易于备份和迁移。
- 利用
.env
文件管理配置: 将敏感信息和不同环境的配置从docker-compose.yml
中分离出来。 - 合理使用
depends_on
: 它能保证启动顺序,但不能保证服务就绪。对于需要等待依赖服务完全就绪的场景,考虑结合healthcheck
。 - 定义自定义网络: 当应用包含多个服务分组或需要更严格的隔离时,使用自定义网络。
- 保持服务职责单一: 每个服务应该只运行一个主要进程,符合容器的最佳实践。
- 编写清晰的
Dockerfile
: 如果使用build
指令,确保你的Dockerfile
是优化的(例如,使用多阶段构建、减少层数、清理临时文件)。 - 版本控制
docker-compose.yml
和Dockerfile
: 将这些文件与你的应用代码一起放入版本控制系统。
8. 总结
Docker Compose 是一个强大而实用的工具,极大地简化了多容器 Docker 应用程序的定义、配置和管理。通过一个描述性的 YAML 文件和几个简单的命令,你可以轻松地启动、停止、伸缩和管理整个应用栈。
掌握 docker-compose.yml
文件的语法和 docker compose
的常用命令是使用 Compose 的关键。从基本的 up
和 down
,到更高级的 exec
, build
, scale
以及多文件、环境变量、健康检查等技巧,Compose 提供了丰富的功能来满足各种应用场景的需求。
通过本文的详细教程和示例,你应该对 Docker Compose 命令的使用有了全面的了解。最好的学习方式是动手实践,尝试用 Compose 定义和运行你自己的多容器应用吧!它将显著提高你的开发效率,并使你的应用部署更加可靠和可重复。