详细对比Docker 命名卷与挂载卷

190 阅读3分钟

翻译引用原文:blog.logrocket.com/docker-volu…

当一个 Docker 容器被销毁时,基于现有 Docker 镜像创建一个新容器不会对原始容器进行任何更改。因此,每当你销毁一个容器并创建一个新容器时,你都会丢失数据。

为了避免丢失数据,Docker 提供了 volumes 和 bind mounts,这两种机制用于在 Docker 容器中持久化数据。在本教程中,我们将探讨 volumes 和 bind mounts,然后查看一些示例和它们的用例。让我们开始吧!

Bind mounts

从 Docker 早期就已经可用,用于数据持久化。Bind mounts 将主机上的文件或目录挂载到容器中,你可以通过其绝对路径引用它。要使用 bind mounts,文件或目录不需要已经存在于 Docker 主机上。如果它不存在,它将根据需要创建。

Bind mounts 依赖于主机文件系统具有特定的目录结构。你必须显式创建用于存储的文件或文件夹的路径。关于 bind mounts 的另一个重要信息是,它们可以访问敏感文件。根据 Docker 文档,你可以通过在容器中运行的进程更改主机文件系统。这包括创建、修改和删除系统文件和目录,这可能会带来相当严重的安全隐患。它甚至可能影响非 Docker 进程。

如何开始使用 bind mounts

要在容器上使用 bind mounts,你有两个标志选项可以使用:--mount-v。这两个选项之间最显著的区别是,--mount 更加详细和明确,而 -v--mount 的简写。它将传递给 --mount 的所有选项合并到一个字段中。

表面上看,这两个命令都创建了一个 PostgreSQL 容器并设置了一个卷来持久化数据。然而,在某些情况下,使用 --mount-v 的区别会非常明显。例如,在处理 services 时,最好使用 --mount,因为你需要指定比 -v 更多的选项。

通过运行以下命令使用 --mount 标志来指定 bind mount:

docker run --rm --name postgres-db -e POSTGRES_PASSWORD=password --mount type=bind,source="$pwd",target=/var/lib/postgresql/data -p 2000:5432 -d postgres

使用以下代码通过 -v 标志指定:

docker run --rm --name postgres-db -e POSTGRES_PASSWORD=password --v "$pwd":/var/lib/postgresql/data -p 2000:5432 -d postgres

请注意,在这两种情况下,我们都指定 $(pwd) 作为源工作目录。基本上,我们告诉 Docker 在我们当前所在的目录中创建 bind mount。

Docker volumes

Docker volumes 是在 Docker 容器中添加数据持久化层的好机制,尤其是当你需要在关闭容器后持久化数据的情况下。Docker volumes 完全由 Docker 自己处理,因此独立于你的目录结构和主机操作系统。当你使用 volume 时,会在主机上的 Docker 存储目录中创建一个新目录,并且 Docker 管理该目录的内容。

使用 volumes 的好处

在 Docker volumes 中,存储不与容器的生命周期绑定,而是存在于其之外。这有许多好处。例如,你可以随意杀死容器而不会丢失数据。还可以轻松地在多个容器中重用存储;例如,一个容器写入存储,而另一个容器从中读取。

由于 volumes 不绑定到任何容器,你可以轻松地同时将它们附加到多个运行的容器中。此外,volumes 不会增加使用它们的 Docker 容器的大小。最后,你可以使用 Docker CLI 管理 volumes,例如,检索卷列表或删除未使用的卷。

如何开始使用 volumes

现在,让我们来看一个示例!假设你想创建一个 PostgreSQL 容器,并且你对持久化数据感兴趣。首先在 $HOME/docker/volumes/postgres 中创建一个名为 postgres 的文件夹。

像 bind mounts 一样,我们可以添加以下代码来指定使用 --mount 标志的 volume:

docker run --rm --name postgres-db -e POSTGRES_PASSWORD=password --mount type=volume,source=$HOME/docker/volumes/postgres,target=/var/lib/postgresql/data -p 2000:5432 -d postgres

或者,使用简写标志 -v 的相同命令如下:

docker run --rm --name postgres-db -e POSTGRES_PASSWORD=password --v $HOME/docker/volumes/postgres:/var/lib/postgresql/data -p 2000:5432 -d postgres

如果你使用 Mac 或 Linux,你必须将数据存储在 $HOME/docker/volumes/ 下,如果你使用 Windows,则存储在 C:\ProgramData\docker\volumes 下。否则,Docker 不会将你的数据视为 volume。

使用场景

在决定何时使用 volumes 或 bind mounts 时,有几个重要的因素需要考虑。如果你希望存储或持久化层完全由 Docker 管理,并且只能通过 Docker 容器和 Docker CLI 访问,你应该选择使用 volumes。然而,如果你需要对存储进行完全控制,并计划允许 Docker 以外的进程访问或修改存储层,那么 bind mounts 是完成这项工作的合适工具。

比较 volumes 和 bind mounts

根据 Docker 文档,使用 volumes 是开始在 Docker 容器中持久化数据的最简单方法。总体而言,bind mounts 相对来说更有限。这与我们迄今为止看到的内容并不令人惊讶。一个好的经验法则是,如果你不确定用于持久化 Docker 容器数据的方法,请使用 volumes。

bind mount 的一个关键区别在于,bind mount 可以被 Docker 之外的进程访问和修改。如前所述,当你希望将 Docker 与其他进程集成时,这可能是一个优势,但如果你担心安全性,这也可能会引起头痛。

结论

现在我们已经看到了 volumes 和 bind mounts 之间的核心区别,让我们回顾一下使 volumes 成为持久化 Docker 数据推荐机制的一些优点。首先,volumes 在容器之间更安全地共享;它们只能在单个目录 ($HOME/docker/volumes) 中指定,并且完全由 Docker 自己管理。你也可以将 volumes 存储在主机之外的远程主机或云提供商上。你可以使用 Docker CLI 和 Docker API 管理 volumes,你还可以从容器中预填充新卷的内容。此外,volumes 在 Linux 和 Windows 上都可以工作,非常适合同时使用两种操作系统的团队。

通过调查 volumes 和 bind mounts,我们已经看到 volumes 在大多数情况下是更好的数据持久化选项。请务必在评论中让我知道你更喜欢哪种方法!