【翻译】Docker应用数据存储
容器内应用创建的数据默认在是容器内部的临时可写入层,这意味着一下问题:
- 当成容器不在不在运行状态时候,这部分数据不会持久化,数据会被丢失。也不方便和其他容器共享数据。
- 数据被写入到容器的临时可写入层,这导致数据迁移困难。
- 数据写入容器临时读写层,这需要操作系统内核提供数据写入驱动,这个额外的抽象,会牺牲一部分写入的性能。
数据保存在宿主机上,意味着你不需要担心容器生命周期结束以后数据会丢失,他会一直保存在宿主的磁盘上。对于在宿主机上存储文件,Docker
提供能了两种方式。这两种方式分别是,挂载文件夹和挂载数据卷,当然你在Linux
上运行Docker
的时候,你也可以使用tmpfs
挂载节点。
选择正确的挂载方式
无论你使用哪种挂载方式,被挂载的文件在容器中表现形式就好像他们正在存在容器中一样,在容器表现出来的形式为文件夹或者是文件。
用一张图来说说明上面介绍到的三种挂载方式之间的区别
- 容器卷: 数据存在宿主机上的一个特定目录(在Linux上: /var/lib/docker/volumes/),除了
Docker
自身进程,其他的进程不应该修改这个目录。挂载数据卷也是目前容器存储数据的最佳方式。 - 挂载目录: 能够保存在宿主机的任何目录,可能保存在一个非常重要的目录中,任何时候这个目录能够其他任何进程读写和修改。
- tmpfs: 只会讲数据保存在宿主机的内存中,永远不会将数据保存宿主的磁盘上。
几种挂载方式的详细说明
- 容器卷:由
Docker
创建并且管理,你也可以手动使用docker volume create
命令创建一个容器卷,或者是在服务启动的时候自动创建。
当你创建好了容器卷以后,就会在宿主机上创建某个目录,这个目录有Docker
进程来管理,你可以将这个容器卷挂载到容器中,这有点类似于文件挂载的方式,只不过这个目录是由Docker
管理,并且与宿主机器上的其他服务隔绝开来。
当你挂载一个容器的时候,这个容器可能是有名字的,也可能是匿名的,匿名的容器被分配了一个随机的以为的名字,匿名容器和有名字的容器在使用方式和表现形式上是一样的。
一个容器卷能够被挂载在躲着容器的内部,当应用容器都停止以后,容器卷还是存在,它不会自动删除,除非你使用docker volume prune
命令来删除它。
容器卷支持给定一个容器卷驱动,他支持将数据保存在远程主机或者是云服务上。
- 文件挂载: 在
Docker
早期,文件挂载非常有用,所有宿主机上的进程都能读取这个文件。相比于挂载容器卷,文件挂载以后有一些功能上的限制。当你在使用一个被从宿主机器上挂载进来的文件以后,这个文件都是直接引用的在宿主机器上文件的绝对地址。如果文件宿主机中不存在,Docker
进程会自动的创建它,文件挂载的性能不错,但是它依赖宿主上的特定文件系统以及目录存储结构。如果你正在开发一个Docker
的应用,请考虑使用容器卷来替代挂载文件的方式。
文件挂载后的隐私问题,这有利有弊,它给了你更大的权利,容器中的应用能够删除,修改,读取被挂载进来的目录,这只能会影响其他的进程服务。你必须权衡利弊。
对于挂载容器卷或者挂载文件,他们的命令行都是一样的,使用--volume
或者-v
选项,对于tmpfs
挂载稍有不同,它使用--tmpfs
选项。然而在17.06 以及更新的版本里面,我们推荐使用--mount
来挂载容器卷或者文件。
容器卷最佳实践
容器卷是我们推荐的容器持久化方式,在使用过程中你需要注意如下事项:
- 多个容器之间可以共享一个容器卷。如果在第一次挂载容器卷的时候,容器卷不存在,那么这个容器就会被自动创建,无论应用容器是否在运行或者停止,容器卷都不会被自动删除,除非你明确的手动删除他。
- 当时宿主机器无法提供存储空间的时候,容器卷配置会失效。
- 当你想存储文件在远程服务器或者云盘上时候,使用容器卷是非常好的选择。
- 当你需要备份,转存,迁移数据的时候,容器卷也是非常好的选择。先关闭使用这个容器卷的容器,然后在再备份容器卷的文件加,类似于(/var/lib/docker/volumes/)。
文件挂载最佳实践
如果你真的需要挂载文件,你需要注意如下事项:
- 容器与宿主机之间共享文件,挂载
/etc/resolv.conf
能够让宿主机和容器有相同的DNS配置。 - 挂载源代码到编译的容器中,例如,你可以挂载源码和maven的target目录到容器,这样编译后的文件其他程序也能访问到。
tmpfs最佳实践
你当你不需要持久化文件的时候你才能选择这个方案,可能是应为安全原因,你需要写入机密数据到宿主机的内存中,你可以使用这个选项。
使用容器卷和文件挂载的技巧
- 如果你挂载了一个空的容器卷到某个有文件的目录,那么这个目录中的文件会被拷贝中容器卷中。如果你如果你挂载某个不存在的容器卷,那么这个容器卷会被自动创建。初始化数据和容器卷的时候能够使用这样的方法。
- 如果你挂载了某个有数据的容器卷到某个空目录,那么容器卷的文件也会被映射到目录中。你甚至可以将
/mnt
挂载到容器中,容器就能读取到usb存储器上的数据。