参考:https://docs.docker.com/storage/
默认情况下,在容器中创建的所有文件都存储在可写容器层中。这意味着:
- 当该容器不再存在时,数据不会持久保存,而且如果另一个进程需要数据,则很难从容器中取出数据。
- 容器的可写层与容器所在的主机紧密耦合。您不能轻易地将数据移动到其他地方。
- 写入容器的可写层需要存储驱动程序来管理文件系统。存储驱动程序使用Linux内核提供一个联合文件系统。与使用直接写入主机文件系统的数据卷相比,这种额外的抽象降低了性能。
Docker为容器提供了两个选项来将文件存储在主机上,这样即使在容器停止后,文件也可以被持久化:volumes 和 bind mounts。如果你在Linux上运行Docker,你也可以使用 tmpfs mount。如果你在Windows上运行Docker,你也可以使用named pipe.
有关这两种数据持久化方法的更多信息,请继续阅读。
一、选择正确的安装类型
无论您选择使用哪种类型的挂载,从容器中看到的数据都是相同的。它以目录或容器文件系统中的单个文件的形式公开。
可视化卷、绑定挂载和tmpfs挂载之间的差异的一个简单方法是考虑数据在Docker主机上的位置。
- 卷存储在由Docker ( /var/lib/docker/volumes/ )管理的主机文件系统的一部分中。非docker进程不应该修改文件系统的这一部分。卷是在Docker中保存数据的最佳方式。
- 绑定挂载可以存储在主机系统的任何位置。它们甚至可能是重要的系统文件或目录。Docker主机或Docker容器上的非Docker进程可以随时修改它们。
- tmpfs挂载只存储在主机系统的内存中,而从不写入主机系统的文件系统。
二、有关挂载类型的更多详细信息
1、Volumes: 由Docker创建和管理。您可以使用 docker volume create 命令显式地创建卷,或者docker可以在容器或服务创建期间创建 卷。
创建卷时,它存储在Docker主机上的目录中。当将卷装入容器时,此目录就是装入容器的目录。这与绑定挂载的工作方式类似,不同 之处在于卷由Docker管理,并且与主机的核心功能隔离。
给定的卷可以同时装入多个容器中。当没有运行的容器使用卷时,该卷仍然对Docker可用,不会自动删除。您可以使用docker volume prune 来删除未使用的卷。
挂载卷时,它可以是命名的或匿名的。当匿名卷第一次挂载到容器中时,不会给它们一个显式的名称,因此Docker会给它们一个随机的名称,这个名称保证在给定的Docker主机中是唯一的。除了名称之外,命名卷和匿名卷的行为方式也相同。
卷还支持使用卷驱动程序,这些驱动程序允许您将数据存储在远程主机或云提供商上。
2、Bind mounts: 可从早期的Docker。与卷相比,绑定挂载的功能有限。使用绑定挂载时,将主机上的文件或目录挂载到容器中。文件或目录由其在主机上的完整路径引用。该文件或目录不需要已经存在于Docker主机上。它是根据需要创建的,如果它还不存在的话。绑定挂载的性能非常好,但是它们依赖于主机的文件系统,该文件系统具有特定的可用目录结构。如果您正在开发新的Docker应用程序,请考虑使用命名卷。不能使用Docker CLI命令直接管理绑定挂载。
绑定挂载允许访问敏感文件
使用绑定挂载的一个副作用是,无论好坏,您都可以通过在容器中运行的进程来更改主机文件系统,包括创建、修改或删除重要的系统文件或目录。这是一种强大的能力,可能具有安全含义,包括影响主机系统上的非docker进程。
3、tmpfs mounts: tmpfs挂载不会持久存储在磁盘上,无论是在Docker主机上还是在容器中。容器可以在容器的生命周期中使用它来存储非持久状态或敏感信息。例如,在内部,swarm服务使用tmpfs挂载来将秘密挂载到服务的容器中。
4、named pipes: npipe挂载可用于Docker主机和容器之间的通信。常见的用例是在容器内运行第三方工具,并使用命名管道连接到Docker引擎API。
绑定挂载和卷都可以使用-v或--volume标记挂载到容器中,但是它们的语法略有不同。对于tmpfs挂载,可以使用--tmpfs标志。但是,在Docker 17.06或更高版本中,我们建议对容器和服务、绑定挂载、卷或tmpfs挂载使用--mount 标志,因为语法更清晰。
三、卷的良好用例
卷是将数据保存在Docker容器和服务中的首选方法。一些卷的用例包括:
- 在多个运行的容器之间共享数据。如果您没有显式地创建它,则在第一次将卷装入容器时将创建它。当该容器停止或删除时,该卷仍然存在。多个容器可以同时挂载同一卷,可以是读写卷,也可以是只读卷。只有当您显式地删除卷时,它们才会被删除。
- 当Docker主机不能保证具有给定的目录或文件结构时。卷可以帮助您将Docker主机的配置与容器运行时解耦。
- 当您希望将容器的数据存储在远程主机或云提供商上,而不是本地时。
- 当您需要备份、恢复或将数据从一个Docker主机迁移到另一个Docker主机时,卷是更好的选择。您可以使用卷停止容器,然后备份卷的目录(例如 /var/lib/docker/volumes/<volume-name> )。
四、绑定挂载的良好案例
通常,您应该尽可能使用卷。绑定挂载适合以下类型的用例:
- 从主机到容器共享配置文件。通过将/etc/resolv.conf从主机挂载到每个容器中,这就是Docker在缺省情况下为容器提供DNS解析的方式。
- 在Docker主机上的开发环境和容器之间共享源代码或构建构件。例如,可以将Maven target/ 目录挂载到容器中,每次在Docker主机上构建Maven项目时,容器就可以访问重新构建的构件。如果您以这种方式使用Docker进行开发,那么您的生产Dockerfile将直接将生产就绪的工件复制到image中,而不是依赖于绑定挂载。
- 当Docker主机的文件或目录结构保证与绑定装载容器所需的一致时。
五、tmpfs 挂载良好案例
tmpfs挂载最适合用于不希望数据在主机上或容器中持久存储的情况。这可能是出于安全原因,或者是为了在应用程序需要编写大量非持久状态数据时保护容器的性能。
六、使用绑定挂载或卷的提示
如果您使用绑定挂载或卷,请记住以下内容:
- 如果将空卷装入文件或目录所在的容器中的目录中,这些文件或目录将传播(复制)到卷中。类似地,如果启动容器并指定一个不存在的卷,则会为您创建一个空卷。这是预填充另一个容器需要的数据的好方法。
- 如果你挂载一个bind mount 或者non-empty volume到容器的一个目录中,这个目录已存在文件或子目录,这些文件或目录被挂载,就像如果你保存文件到 /mnt Linux主机上然后u盘挂载到/mnt。/mnt的内容会被USB驱动器的内容所掩盖,直到USB驱动器被卸载。被隐藏的文件不会被删除或更改,但是在绑定挂载或卷被挂载时无法访问。