再見二丁目 | yitimo的个人博客

再见二丁目

【翻译】在 Docker 管理数据

发布于: 2024-01-27 15:46

原文链接:Manage data in Docker

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

Docker有两个可选配置来保证即使容器停止了, 文件也能持久存储在宿主机上: 卷(volumes) 和 绑定挂载(bind mounts).

同时Docker还支持容器将文件存储在宿主机内存里. 这些文件不是持久化存储的. 如果你在 linux 上运行 Docker, 会使用 tmpfs 挂载来保存文件到宿主机内存里. Windows下则用的是命名管道(named pipe).

选择正确的挂载方式

无论你选择用那种方式来挂载文件, 对容器来说数据都是相同的. 最终都是暴露为容器文件系统里的一个目录或文件.

一个简单的形容数据卷、绑定挂载和tmpfs挂载区别的方式是想象数据如何在Docker宿主里存在.

type of mounts

绑定挂载合数据卷都能用 -v--volume 标识挂在到容器里, 但是有略微不同. 而对于tmpfs挂载, 你可以使用 --tmpfs 标识. 我们推荐容器和服务都用 --mount 来使用绑定挂载, 数据卷, 或者 tmpfs 挂载, 这样语法更加清晰.

数据卷

数据卷由Docker来创建和管理. 你可以直接使用 docker volume create 命令来创建一个数据卷, 或者由Docker在创建容器或服务时自动创建.

当创建好一个数据卷时, 它被存储在宿主机的一个目录下. 当把数据卷挂载到容器时, 这个目录就被挂在到了容器下. 这个行为与绑定挂载类似, 不过数据卷是由Docker来管理, 与宿主机的核心系统隔离.

一个数据卷可以同时被挂在到多个容器下. 当没有运行中的容器使用到时, 这个数据卷对Docker来说也仍然存在, 不会被自动删除. 你可以用 docker volume prune 命令来删除所有未被使用的数据卷.

当你挂载了一个数据卷, 它可能是具名的或匿名的. 匿名数据卷会由Docker生成一个随机的唯一标识. 和具名数据卷一样, 即使你删除了容器, 匿名数据卷也会继续存在. 除非你在创建容器时用了 --rm 标识. 如果在创建容器时加了 --rm 标识, Docker就会自动移除匿名数据卷. 具体可查看移除匿名数据卷.

数据卷同时还支持卷驱动器, 这让你可以将数据存储在远程主机或云提供商等更多可能的地方.

绑定挂载

绑定挂载相比数据卷有几个限制. 当使用了绑定挂载, 一个宿主机上的文件或目录就会被挂在到容器里. 这个文件或目录通过其在宿主机上的完整路径被引用. 这个文件或目录不一定已经存在于宿主机上. 如果未存在则会自动创建. 绑定挂载很快, 但是宿主机的文件系统需要指定一个目录结构给它. 如果你在开发新的Docker应用, 可以考虑改用具名数据卷. 你不能用Docker的cli命令来直接管理绑定挂载.

重要

绑定挂载默认会赋予宿主机上文件的写权限

使用绑定挂载的一个副作用是, 你可以通过运行在容器里的进程来更改宿主机的文件系统, 包括创建、修稿或删除重要的系统文件或目录. 这是个强大的能力, 会有安全方面的影响, 包括影响到宿主机上的非Docker进程.

提示

代码库较大或用到了多仓库(monorepos), 或是用到了不再随代码增大的虚拟文件系统吗? 可以看看同步文件共享. 这提供了快速且弹性的宿主到虚拟机的文件共享能力, 其使用同步文件系统缓存来强化了绑定挂载的性能.

tmpfs

tmpfs挂载不论在容器内还是宿主机上都不会存储到硬盘上. 其可以在容器生命周期内被使用, 用来保存非持久化的状态或敏感信息. 例如, Swarm服务内部就使用了tmpfs来挂载秘钥到服务的容器里.

具名管道

具名管道可以用于Docker宿主和容器间的通信. 一个常用场景是在容器内通过第三方工具来连接到Docker引擎的API.

适合用数据卷的情况

数据卷是在Docker容器或服务里持久化存储数据时更推荐的方式. 一些使用场景包括:

适合用绑定挂载的情况

通常来说你应该尽量使用数据卷. 绑定挂载则适用于这些情况:

适合用 tmpfs 挂载的情况

tmpfs挂载最适合用在当你不想数据被保存到容器里或宿主机上时. 这可能是出于安全原因, 或是应用需要写入较大的非持久化数据时用来保证性能.

使用绑定挂载或数据卷时的注意事项

当你使用绑定挂载或者数据卷时, 注意以下事项:

下一步