Docker 卷是什么?

2025 年 6 月 16 日 | 阅读 6 分钟

Docker 卷是在容器中工作时确保数据持久性的广泛使用且有用的工具。Docker 卷是挂载到 Docker 容器的文件系统,用于保存正在运行的容器生成的数据。

  • 当容器不再存在时,数据不会持久化,如果其他进程需要容器中的数据,则很难将其取出。
  • 容器的可写层与容器运行的宿主机紧密耦合。数据不易移动到其他地方。
  • 写入容器的可写层需要一个存储驱动程序来管理文件系统。

Docker 提供了两个选项,供容器在宿主机上存储文件,以便在容器停止后文件仍然可以持久化。

  1. 卷 (Volumes) 存储在由 Docker 管理的宿主机文件系统的某个部分。
  2. 绑定挂载 (Bind mounts) 可以存储在宿主机系统的任何位置

卷存储在宿主机上,独立于容器的生命周期。这使得用户可以轻松备份数据并在容器之间共享文件系统。

What is Docker Volume

挂载类型

在所有类型的挂载中,从容器内部看数据是相同的。它以目录或单个文件的形式暴露在容器的文件系统中。

1. 卷 (Volumes):卷存储在宿主机文件系统的某个部分,由 Docker 管理(在 Linux 上是 /var/lib/docker/volumes/)。非 Docker 进程不应修改该文件系统的这部分。卷是持久化 Docker 数据最佳方式。我们可以使用 `docker volume create` 命令显式创建一个卷,或者 Docker 可以在创建容器或服务时创建一个卷。

当我们创建一个卷时,它存储在 Docker 宿主机的某个目录中。卷由 Docker 管理,并且独立于宿主机系统的核心功能。

一个给定的卷可以同时挂载到多个容器中。当没有正在运行的容器使用卷时,卷仍然可以被 Docker 使用,并且不会自动删除。但是,我们可以使用 `docker volume prune` 删除未使用的卷。

当我们挂载一个卷时,它可以是命名卷匿名卷。匿名卷在首次挂载到容器时没有显式名称,因此 Docker 会给它们一个随机名称,保证在给定的 Docker 宿主机上是唯一的。除了名称,命名卷和匿名卷的行为方式相同。

卷还支持卷驱动程序,允许将数据存储在远程主机或云提供商上,以及其他可能性。

2. 绑定挂载 (Bind mounts):绑定挂载可以存储在宿主机系统的任何位置。它们可能是重要的系统文件或目录。宿主机上的非 Docker 进程或 Docker 容器可以随时修改它们。与卷相比,绑定挂载的功能有限。

当我们使用绑定挂载时,宿主机上的文件或目录会被挂载到容器中。文件或目录通过其在宿主机上的完整路径来引用。文件或目录不需要预先存在于 Docker 宿主机上。如果它尚不存在,则会在需要时按需创建。

绑定挂载非常高效,但它们依赖于宿主机的文件系统,并且需要特定的目录结构。如果我们想开发新的 Docker 应用程序,请考虑使用命名卷而不是绑定挂载。我们不能使用 Docker CLI 命令直接管理绑定挂载。

3. tmpfs 挂载:tmpfs 挂载仅存储在宿主机系统的内存中,并且永远不会写入宿主机的文件系统。它不会持久化到磁盘,无论是在 Docker 宿主机上还是在容器内。

tmpfs 挂载可以在容器的生命周期内用于存储非持久化状态或敏感信息。

4. 命名管道 (named pipes):命名管道挂载可用于宿主机和容器之间的通信。常见的用例是在容器中运行第三方工具,并使用命名管道连接到 Docker Engine API。

绑定挂载和卷都可以使用 **-v** 或 **--volume** 标志挂载到容器中,但它们的语法略有不同。

在 Docker 17.06 及更高版本中,我们对容器和服务都使用 **--mount** 标志,用于绑定挂载、卷或 tmpfs 挂载。

-v 或 --mount 标志

**-v** 或 **--volume** 标志曾用于独立容器,而 **--mount** 标志曾用于 Swarm 服务。但是,从 Docker 17.06 开始,我们也可以将 **--mount** 与独立容器一起使用。

总的来说,**--mount** 更明确、更冗长。最大的区别在于 **-v** 语法将所有选项组合在一个字段中,而 **--mount** 语法将它们分开。

新用户应尝试 **--mount** 语法,因为它比 **--volume** 语法更简单。如果用户需要指定卷驱动程序选项,则应使用 **--mount**。

1. -v 或 --volume:它包含三个字段,用冒号(:)分隔。字段必须按正确顺序排列,但每个字段的含义不易直接理解。

  • 对于命名卷,第一个字段是卷的名称,它在给定的宿主机上是唯一的。对于匿名卷,第一个字段被省略。
  • 第二个字段是文件或目录在容器中挂载的路径。
  • 第三个字段是可选的,由逗号分隔的选项列表。

2. --mount:它包含多个键值对,用逗号分隔,每个键值对由 **<key>=<value>** 组成。 **--mount** 语法比 -v 或 -volume 更冗长。键的顺序不重要,但该标志的值更容易理解。

  • 挂载的类型,可以是 **volume, bind**,或 **tmpfs**。
  • 目标 (destination) 的值是文件或目录在容器中挂载的路径。它可以指定为 **destination, dst**,或 **target**。
  • 如果存在 read-only 选项,则会导致绑定挂载以只读方式挂载到容器中。
  • volume-opt 选项可以指定多次,它接受一个键值对,由选项名称及其值组成。

如何创建和管理卷

创建卷

使用以下命令在容器范围之外创建和管理 Docker 卷。

Docker 会在宿主机下的 **/var/lib/docker/volume/path** 目录中自动创建一个卷。

现在将此卷挂载到容器上,以确保数据持久化和多个容器之间的数据共享。

列出卷

使用以下命令列出卷

输出显示卷的列表,指定它们的挂载点和卷名。

检查卷

使用以下命令检查卷。

它列出了卷的所有详细信息,包括其在宿主机上的位置(挂载点),以及数据卷中存储的所有内容也可以在挂载点路径下的目录中找到。

挂载数据卷

要将数据卷挂载到容器,请在 **docker run** 命令中添加 **--mount** 标志。它将卷添加到指定的容器中,并将虚拟环境内部生成的数据存储起来。使用以下语法运行容器并将其挂载一个数据卷。

存储在该目录中的所有内容也会自动保存在宿主机上的数据卷中。

删除卷

要删除 Docker 卷,我们需要指定其名称。使用以下基本命令语法来删除卷。

Docker 仅在卷未使用时才删除它们。如果存在使用指定卷的容器,它会响应错误。

一次删除所有卷

使用以下命令一次性删除所有未使用的 Docker 卷

输出会一次性警告,提示它将删除所有未被至少一个容器使用的本地卷,然后需要您确认继续。