Docker存储(一)

简介

默认情况下,容器中创建的所有文件都存储在可写容器层中。产生的问题是:

  • 当容器停止后,数据不会持久化,并且如果另一个进程需要该数据,很难从容器中读取。
  • 容器的可写层与运行容器的主机紧密耦合,无法简单地将数据移动到其他地方。
  • 向容器内写入文件,需要一个存储驱动程序来管理文件系统。与直接写入主机文件系统的数据卷相比,这样会降低性能。

Docker提供了两种方式,让容器将文件存储在主机上,即使容器停止后文件也能持久化:

  • 数据卷
  • 绑定挂载点

Docker 还支持容器在主机内存中存储文件。

  • 在 Linux 上运行 Docker,使用tmpfs挂载;
  • 在 Windows 上运行 Docker,使用命名管道;

这几种方式,在容器内部看来,是完全一样的。从外部来看如下图所示:

在这里插入图片描述

卷是在 Docker 容器和服务中持久化数据的首选方式。

卷存储在由Docker管理的主机文件系统中(在Linux上为 /var/lib/docker/volumes/)。非Docker进程不应修改此文件系统的此部分。

卷由Docker创建和管理。可以使用docker volume create命令显式创建卷,也可以在容器创建时创建卷。

给定的卷可以同时挂载到多个容器中。当没有运行容器使用卷时,该卷仍然可用,并且不会自动删除。可以使用docker volume prune删除未使用的卷。

推荐使用场景

  1. 在多个运行的容器之间共享数据。

  2. 不能保证 Docker 主机有给定的目录或文件结构时。可以通过卷来与主机的配置解耦。

  3. 需要将容器的数据存储在远程主机或云提供商上。

  4. 需要从一个 Docker 主机备份、恢复或迁移数据时,卷是更好的选择。直接备份该卷的目录(/var/lib/docker/volumes/)。

  5. 需要高性能 I/O 时。卷存储在 Linux VM 中而不是主机中,这意味着读写具有更低的延迟和更高的吞吐量。

  6. 需要完全本地文件系统行为时。

    例如,数据库引擎需要精确控制磁盘刷新,以保证事务的耐久性。卷存储在 Linux VM 中并可以提供这些保证,而绑定挂载则被转移到 macOS 或 Windows,其中文件系统行为略有不同。

挂载点

绑定挂载可以存储在主机系统的任何位置。包括系统文件。在Docker主机或Docker容器上的非Docker进程可以随时修改它们。
与卷相比,绑定挂载的功能有限。

绑定挂载,是将主机机器上的文件或目录挂载到容器中。需要主机上的文件(目录)的完整引用路径。

绑定挂载非常高效,缺点是要依赖于主机的文件系统是否有这样的目录结构,并且,无法使用Docker CLI命令直接管理绑定挂载。

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

一般来说,应该尽可能使用卷。

绑定挂载适用场景

  • 从主机共享配置文件到容器。这是Docker默认提供DNS解析到容器的方式,即将主机机器的/etc/resolv.conf挂载到每个容器中。

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

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

tmpfs

tmpfs挂载在主机或容器内部都不会保留在磁盘上。它可以在容器的生命周期内被容器使用,用于存储非持久状态或敏感信息。例如,Swarm服务使用tmpfs挂载将Secret信息挂载到服务的容器中。

适用场景

  • 不希望数据在主机或容器内持久化的情况。例如:安全原因;
  • 当应用程序为了容器性能,需要写入大量非持久状态数据时。

命名管道

npipe挂载可用于Docker主机和容器之间的通信。

常见用例是在容器内部运行第三方工具,并使用命名管道连接到Docker Engine API。