好的,docker-compose 是 Docker 生态中用于定义和运行多容器 Docker 应用程序的核心工具。它非常强大且极其常用,绝对值得一份详细的教程。

docker compose 通过一个 文件(docker-compose.yml)来配置应用服务,然后使用一个简单的命令,就可以从该配置中创建并启动所有服务。

这是一份从入门到实践的详细 docker-compose 使用教程。


 

1. 为什么需要 docker-compose

 

想象一下,你有一个 Web 应用,它至少需要三个组件:

  1. 一个 Web 服务器(如 Nginx)
  2. 一个应用服务器(如 Python/Node.js)
  3. 一个数据库(如 PostgreSQL)

使用 Docker,你需要为每个组件单独运行 docker run ... 命令,并手动管理它们之间的网络连接(--link 或创建 docker network)、数据卷(-v)和环境变量(-e)。这个过程非常繁琐且容易出错。

docker-compose 允许你在一个 文件中声明式地定义所有这些服务、网络和卷,然后用一个命令管理它们的整个生命周期(启动、停止、重建)。


 

2. 安装

 

在现代 Docker 安装中(例如通过 Docker Desktop for Mac/Windows/Linux 或在 Linux 上使用官方安装脚本),docker compose (V2) 通常已经包含在内

1. 验证安装:

 

\2. (如果未安装) 在 Linux 上安装:

如果你的 docker 版本较旧,或安装时未包含该插件,可以手动安装:

方法一 (推荐):使用 Docker 的 apt/yum 仓库

 

方法二:手动下载 (备用)

 


 

3. 核心文件:docker-compose.yml

 

docker-compose 的所有魔力都在这个 文件中。它有几个顶层关键字段:

 

docker-compose.yml 结构详解

 

我们将重点讲解最核心的 services 部分。


 

4. 核心概念:服务发现

 

在上面的例子中,api 服务如何连接到 db 服务?

当所有服务都连接到同一个自定义网络app-network)时,Docker 会自动提供 DNS 服务发现。这意味着 api 容器内可以直接通过服务名 db 作为主机名 (Hostname) 来访问 db 容器的 IP 地址。

这解决了容器 IP 地址不固定的问题,是 docker-compose 的核心优势之一。


 

5. 核心概念:使用 .env 文件

 

永远不要把密码、API 密钥等敏感信息硬编码到 docker-compose.yml 文件中(因为你可能需要把这个文件提交到 Git)。

最佳实践是使用 .env 文件。docker compose 会自动加载docker-compose.yml 同目录下的 .env 文件。

1. 创建 .env 文件 (并将其添加到 .gitignore):

 

2. 在 docker-compose.yml 中引用:

 


 

6. 核心命令(常用操作)

 

假设你已经在 docker-compose.yml 所在的目录中。

 

6.1. 启动应用 (创建并运行)

 

docker compose up

 

6.2. 停止并移除应用

 

docker compose down

 

6.3. 临时停止/启动 (不移除)

 

docker compose stop

docker compose start

docker compose restart

 

6.4. 查看状态与日志

 

docker compose ps

docker compose logs

 

6.5. 在运行的容器中执行命令

 

docker compose exec

 

6.6. 更新镜像

 

docker compose pull

docker compose build

docker compose up -d 最后使用该命令重新创建并启动最新版容器


 

7.volumes详解

docker-compose.yml 文件中的 "顶层卷声明" (Top-Level Volume Declaration)

它的作用是告诉 docker compose:“请为我创建并管理两个命名卷 (Named Volumes),一个叫 nginx-data,另一个叫 db-data。”

下面是详细的解释,包括它为什么存在以及如何工作。


 

7.1. 🤔 为什么需要 volumes?(The Problem)

 

容器是“短暂”的 (Ephemeral)。

当你运行 docker compose up -d,它会创建容器。当你运行 docker compose down 来停止和移除应用时,这些容器会被彻底销毁

...那么在 docker compose down 之后,所有这些数据都会永久丢失

 

7.2. 💡 volumes 如何解决问题?(The Solution)

 

命名卷 (Named Volumes) 就是 Docker 官方推荐的数据持久化方案。

一个“命名卷”是:

  1. 一个由 Docker 在宿主机(你的电脑或服务器)上创建和管理的特殊存储区域。
  2. 它有一个唯一的名称(比如 db-data)。
  3. 它的生命周期与容器无关

 

7.3. 🧩 docker-compose 中的两部分

docker-compose 中使用 volumes 分为两步

第 1 部分:顶层 volumes: (你问的)

 

第 2 部分:服务级 volumes: (如何使用)

光声明了“数据桶”还不够,你必须告诉服务(容器)如何去使用它们。这在 services: 内部完成。

工作流程解释 (db 服务):

  1. docker compose 看到 db 服务需要挂载一个叫 db-data 的卷。
  2. 它去顶层的 volumes: 声明里查找,发现 db-data 已经被定义了。
  3. 当启动 db 容器时,Docker 会把这个持久化的 db-data(在宿主机上)“挂载”到容器内部/var/lib/mysql 路径上。

结果:

当 db 容器内的 MySQL 进程向 /var/lib/mysql 写入数据时,这些数据实际上被直接写入到了宿主机上的 db-data 卷中。

 

7.4. ✨ 带来的好处 (Benefits)

 

使用这种方式,你可以获得:

  1. 数据持久化:

    当你运行 docker compose down 时,db 容器被销毁,但 db-data 卷依然存在,里面的数据完好无损。

  2. 平滑升级:

    下一次你运行 docker compose up -d(比如为了升级 MySQL 镜像),docker compose 会创建一个新的 db 容器,并把现有的 db-data 卷重新挂载到新容器的 /var/lib/mysql 目录。你的所有数据都还在。

  3. 数据与容器解耦:

    你的数据(db-data)和你的应用逻辑(db 容器)的生命周期是分开的,这在运维中至关重要。

 

8. 实战演练:部署 WordPress (Web + 数据库)

 

这是一个经典的 docker-compose 示例。

1. 创建项目目录:

 

2. 创建 .env 文件 (用于数据库密码):

 

3. 创建 docker-compose.yml 文件:

4. 启动应用:

 

5. 访问:

等待一两分钟让 WordPress 和数据库完成初始化。

在浏览器中打开 http://<你的服务器IP>:8000,你将看到 WordPress 的安装界面。

6. 清理:

当你测试完毕,可以运行: