存储

默认情况下,在容器内创建的所有文件都存储在可写的容器层上。这意味着

  • 当该容器不再存在时,数据不会持久化,如果另一个进程需要该数据,则很难从容器中获取该数据。
  • 容器的可写层与运行容器的主机紧密耦合。您无法轻松地将数据移动到其他位置。
  • 写入容器的可写层需要一个存储驱动程序来管理文件系统。存储驱动程序提供联合文件系统,使用Linux内核。与使用 *数据卷* 直接写入主机文件系统相比,这种额外的抽象降低了性能。

Docker 提供了两种选项,使容器能够在主机上存储文件,以便即使在容器停止后也能持久化文件:卷和绑定挂载。

Docker 还支持容器在主机上的内存中存储文件。此类文件不会持久化。如果您在Linux上运行Docker,则使用tmpfs挂载在主机的系统内存中存储文件。如果您在Windows上运行Docker,则使用命名管道在主机的系统内存中存储文件。

选择合适的挂载类型

无论您选择使用哪种类型的挂载,数据在容器内的外观都相同。它作为容器文件系统中的目录或单个文件公开。

一种轻松直观卷、绑定挂载和tmpfs挂载之间差异的方法是考虑数据在Docker主机上的存储位置。

Types of mounts and where they live on the Docker host
  • 卷存储在Docker *管理* 的主机文件系统的一部分(Linux上的/var/lib/docker/volumes/)。非Docker进程不应修改文件系统的这部分。卷是持久化Docker数据最佳方式。

  • 绑定挂载可以存储在主机系统的任何位置。它们甚至可能是重要的系统文件或目录。Docker主机上的非Docker进程或Docker容器可以随时修改它们。

  • tmpfs挂载仅存储在主机系统的内存中,并且永远不会写入主机系统的文件系统。

绑定挂载和卷都可以使用-v--volume标志安装到容器中,但每个标志的语法略有不同。对于tmpfs挂载,您可以使用--tmpfs标志。我们建议对容器和服务都使用--mount标志,用于绑定挂载、卷或tmpfs挂载,因为语法更清晰。

卷由Docker创建和管理。您可以使用docker volume create命令显式创建卷,或者Docker可以在创建容器或服务期间创建卷。

创建卷时,它存储在Docker主机上的目录中。将卷安装到容器中时,此目录就是安装到容器中的内容。这类似于绑定挂载的工作方式,只是卷由Docker管理,并且与主机的核心功能隔离。

给定的卷可以同时安装到多个容器中。当没有运行的容器使用卷时,卷仍然可用于Docker,不会自动删除。您可以使用docker volume prune删除未使用的卷。

安装卷时,它可能是命名的或匿名的。匿名卷被赋予一个随机名称,该名称在给定的Docker主机中保证是唯一的。与命名卷一样,匿名卷即使删除使用它们的容器也会持久化,除非在创建容器时使用--rm标志,在这种情况下,匿名卷将被销毁。请参见删除匿名卷。如果您一个接一个地创建多个使用匿名卷的容器,则每个容器都会创建自己的卷。匿名卷不会自动在容器之间重用或共享。要在两个或多个容器之间共享匿名卷,必须使用随机卷ID安装匿名卷。

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

绑定挂载

与卷相比,绑定挂载的功能有限。使用绑定挂载时,主机上的文件或目录会被挂载到容器中。该文件或目录通过其在主机上的完整路径引用。该文件或目录不必已存在于 Docker 主机上。如果它尚不存在,则会按需创建。绑定挂载速度很快,但它们依赖于主机文件系统具有可用的特定目录结构。如果您正在开发新的 Docker 应用程序,请考虑改用命名卷。您无法使用 Docker CLI 命令直接管理绑定挂载。

重要

绑定挂载默认允许写入主机上的文件。

使用绑定挂载的一个副作用是,您可以通过在容器中运行的进程更改主机文件系统,包括创建、修改或删除重要的系统文件或目录。这是一种强大的功能,可能存在安全隐患,包括影响主机系统上的非 Docker 进程。

提示

处理大型代码库或单体库,或者使用虚拟文件系统但其扩展性已无法满足代码库需求?请查看 同步文件共享。它通过使用同步文件系统缓存来增强绑定挂载性能,从而提供快速灵活的主机到虚拟机文件共享。

tmpfs

tmpfs 挂载不会持久保存到磁盘上,无论是 Docker 主机还是容器内。容器在其生命周期内可以使用它来存储非持久性状态或敏感信息。例如,在内部,Swarm 服务使用 tmpfs 挂载将 密钥 挂载到服务的容器中。

命名管道

命名管道 可用于 Docker 主机和容器之间的通信。常见的用例是在容器内运行第三方工具并使用命名管道连接到 Docker Engine API。

卷的良好用例

卷是首选的持久化 Docker 容器和服务中的数据的方式。卷的一些用例包括:

  • 在多个正在运行的容器之间共享数据。如果您没有显式创建它,则在第一次将其挂载到容器中时会创建一个卷。当该容器停止或被删除时,卷仍然存在。多个容器可以同时挂载同一个卷,可以是读写或只读。只有在您显式删除卷时,卷才会被删除。

  • 当无法保证 Docker 主机具有给定的目录或文件结构时。卷有助于将 Docker 主机的配置与容器运行时分离。

  • 当您希望将容器的数据存储在远程主机或云提供商上,而不是本地时。

  • 当您需要备份、恢复或将数据从一个 Docker 主机迁移到另一个 Docker 主机时,卷是更好的选择。您可以停止使用该卷的容器,然后备份该卷的目录(例如 /var/lib/docker/volumes/)。

  • 当您的应用程序需要 Docker Desktop 上的高性能 I/O 时。卷存储在 Linux 虚拟机中而不是主机中,这意味着读写具有更低的延迟和更高的吞吐量。

  • 当您的应用程序需要 Docker Desktop 上完全原生的文件系统行为时。例如,数据库引擎需要精确控制磁盘刷新以保证事务持久性。卷存储在 Linux 虚拟机中,可以提供这些保证,而绑定挂载则远程连接到 macOS 或 Windows,其文件系统行为略有不同。

绑定挂载的良好用例

一般来说,应尽可能使用卷。绑定挂载适用于以下类型的用例:

  • 将配置文件从主机共享到容器。这就是 Docker 默认情况下如何通过将主机上的 /etc/resolv.conf 挂载到每个容器中来为容器提供 DNS 解析。

  • 在 Docker 主机上的开发环境和容器之间共享源代码或构建工件。例如,您可以将 Maven target/ 目录挂载到容器中,每次在 Docker 主机上构建 Maven 项目时,容器都可以访问重建的工件。

    如果您以这种方式使用 Docker 进行开发,您的生产 Dockerfile 将直接将生产就绪的工件复制到镜像中,而不是依赖绑定挂载。

  • 当 Docker 主机的文件或目录结构保证与容器所需的绑定挂载一致时。

tmpfs挂载的良好用例

tmpfs 挂载最适合不需要在主机或容器中持久化数据的情况。这可能是出于安全原因,或者当您的应用程序需要写入大量非持久性状态数据时,为了保护容器的性能。

使用绑定挂载或卷的提示

如果您使用绑定挂载或卷,请记住以下几点:

  • 如果您将空卷挂载到容器中存在文件或目录的目录中,这些文件或目录将被传播(复制)到卷中。同样,如果您启动一个容器并指定一个尚不存在的卷,则会为您创建一个空卷。这是一种预填充另一个容器需要的数据的好方法。

  • 如果您将绑定挂载或非空卷挂载到容器中存在某些文件或目录的目录中,则这些文件或目录将被挂载所遮蔽,就像您将文件保存到 Linux 主机上的 /mnt 中,然后将 USB 驱动器挂载到 /mnt 中一样。/mnt 的内容将被 USB 驱动器的内容遮蔽,直到 USB 驱动器被卸载。被遮蔽的文件不会被删除或更改,但在绑定挂载或卷挂载时不可访问。

后续步骤

  • 了解更多关于 的信息。
  • 了解更多关于 绑定挂载 的信息。
  • 了解更多关于 tmpfs 挂载 的信息。
  • 了解更多关于 存储驱动程序 的信息,它们与绑定挂载或卷无关,但允许您将数据存储在容器的可写层中。