概述

容器中创建的文件默认会写入可写的容器层,这意味着:

  • 这些数据会随着容器的销毁而消失
  • 容器的可写层与当前宿主机耦合在了一起,想要将数据转移到别的地方比较麻烦
  • 需要借助存驱动来对文件系统进行管理才能对容器的可写层进行写入,这与使用数据卷相比性能会差一些,因为多了一层抽象层。

Docker 针对数据存储的问题提供了两种解决方案:volumnbind mount,这使得我们能够放心的将容器中产生的数据存储在宿主机中。

如果你的 Docker 运行在 Linux 上,那么你还有另外一种选择: tmpfs mount

选择正确的挂载方式

不管你选择使用哪一种挂载方式,在容器内看起来都是一样的。但是从容器外的角度来看,这三种挂载方式的确存在不同,下图展示了三种挂载方式的区别:

  • Volume 是由 Docker 管理的宿主机文件系统的一部分,非 Docker 进程一般不应该修改这部分数据。Volume 是用于存储容器中数据的最好的方式。当你创建一个 volume 时,其会被存储在 Docker 宿主机的一个目录中,当你把这个 Volume 挂载到容器中时,这个目录就会被挂载到容器中。这与 bind mount 的运作方式有些相似,但不同之处是 volume 是由 Docker 管理且与宿主机的核心功能隔离的。一个 volume 能挂载到多个容器中,且在一个 Docker 宿主机中,volume 的名称必须是唯一的,如果我们没有显式指定该名称,Docker 就会在 volume 被挂载到容器上时设定一个随机的名称。同时,volume 支持使用不同的 Volume Driver,使得我们能够将容器产生的数据存储在远程的主机或是云服务提供者处。
  • Bind Mount 可以存储在宿主机中的任何位置,其甚至可以是一些重要的系统文件或目录。宿主机中的非 Docker 进程和其他容器能够随时修改这些数据。这是 Docker 早期使用的功能,使用 bind mount 能够将宿主机上的文件或目录挂载到容器中。若你在开发新的 Docker 应用,建议使用具名 volume 而不是 bind mount。
  • tmpfs Mount 存储在宿主机的内存中,这些数据并不会写入到宿主机的文件系统中。其在容器声明周期中能够一直使用,一般用于存储一些非持久状态或是敏感信息。swarm service 就使用 tmpfs 来将 secret 挂载到 service 容器中。

最佳实践

Volumes 的最佳实践

  • 在多个正在运行的容器之间共享数据。
  • 当宿主机不能保证提供特定的文件或目录结构时,使用 volume 来将容器运行时和宿主机进行解耦。
  • 当你想将容器中的数据存在远程的主机或是云服务提供商处时。
  • 当你需要在容器宿主机之间进行备份,恢复或是数据迁移时。

bind mouts 的最佳实践

  • 在宿主机和容器之间共享某些配置文件。
  • 在宿主机和容器的开发环境中共享源码或构建产物。
  • 当 Docker 宿主机的文件或目录结构保证与容器 bind mount 中所需的一致时。

tmpfs 的最佳实践

  • 用于存储某些不需要进行持久化的数据,如敏感信息。

Tips

  • 如果你将一个空的 volume挂载到容器中的某个已经存在某些文件或目录的目录下时,这些已经存在文件或目录会被复制到 volume 中。类似的,如果你在启动容器时指定了一个不存在的 volume,那么 Docker 会帮你创建一个空的 volume。
  • 如果你将一个 bind mount 或 非空的 volume 挂载到已经存在的某些文件或目录的下时。纳闷这些文件在 bind mount 或 volume 被卸载前都会被隐藏起来。