概述
Docker 有两种方式可以持久化数据,分别是 volume
和 bind mount
,当然,还有其他的方式,例如 Linux 下的 tmpfs
和 windows 下的 named pipe
,但是都不是通用的,所以这里就不展开。这篇文章主要介绍一下 volume
和 bind mount
的区别以及使用场景,并且对其中一些细节的东西拿出来说一下。
数据管理图
图 1:Docker 常用数据管理方式 |
---|
From: https://docs.docker.com/storage/volumes/ |
使用入门
volume 使用
[[email protected]]# docker volume create redis
[[email protected]]# docker run -v redis:/data redis:6.0 redis-server
bind mount 使用
[[email protected]]# docker run -v /myredis/conf:/usr/local/etc/redis redis redis-server
持久化方式选择
volume 使用场景
卷是在 Docker 容器和服务中持久化数据的首选方式。卷的一些使用场景包括:
- 在多个运行的容器之间共享数据。如果你没有显式地创建它,volume 在第一次安装到容器中时就会被创建。当该容器停止或被移除时,volume 仍然存在。多个容器可以同时挂载同一个 volume,可以是读写式的,也可以是只读式的。只有当你明确删除卷时,卷才会被删除;
- 当 Docker 主机不能保证拥有给定的目录或文件结构时,volume 可以将 Docker 主机的配置与容器运行时解耦;
- 当您想将容器的数据存储在远程主机或云提供商上时;
- 当你需要将数据从一个 Docker 主机备份、还原或迁移到另一个 Docker 主机时,volume 是一个更好的选择。你可以停止使用 volume 的容器,然后备份 volume 的目录(如
/var/lib/docker/volumes/<volume-name>
)。 - 当你的应用需要在 Docker Desktop 上进行高性能的 I/O 时。volume 存储在 Linux 虚拟机中,而不是主机中,这意味着读写的延迟和吞吐量要低得多。
- 当你的应用需要在 Docker Desktop 上实现完全原生的文件系统行为时。例如,数据库引擎需要精确控制磁盘冲洗以保证事务的耐久性。Volume 存储在 Linux 虚拟机中,可以做出这些保证,而绑定挂载则会被远程到 macOS 或 Windows 中,文件系统的行为略有不同。
bind mount 使用场景
一般来说,您应该尽可能地使用 volume。bind mount
适用于以下场景:
- 将配置文件从主机共享给容器。这是 Docker 默认向容器提供 DNS 解析的方式,通过将主机上的 /etc/resolv.conf 挂载到每个容器中;
- 在 Docker 主机上的开发环境和容器之间共享源代码或构建组件。例如,你可以将 Maven
target/
目录挂载到容器中,每次在 Docker 主机上构建 Maven 项目时,容器都可以访问重建的组件;
如果你以这种方式使用 Docker 进行开发,你的生产 Dockerfile 会直接将生产就绪的组件复制到镜像中,而不是依赖绑定挂载; - 当保证 Docker 主机的文件或目录结构与容器所需的绑定挂载一致时。
使用方式
无论是 volume
还是 bind mount
,都可以通过 -v/--volume
或者 --mount
来使用,-v
和 --mount
区别是:
-v
(--volume
):简单直接--mount
:更加明确,但冗长,如果你需要指定 mount 的参数,那么你应该用这一个
额外提示
容器目录不为空
- 如果你挂载一个
volume
到容器内的目录,但是这个目录里面已经有内容了,那么这个时候具体表现取决于你的volume
是否是空的- 如果
volume
是空的,那么容器内目录的内容会被拷贝到volume
中; - 如果
volume
不空,那么容器内的目录就会被隐藏,但是不会被删除或者修改。
- 如果
- 如果是使用的
bind mount
方式,那么无论是否主机内的目录为空,容器内的目录都会被隐藏。
主机目录/volume 不存在
如果使用 -v
指定 volume
或者主机的目录,但是这个目录或者 volume
不存在,那么 docker 的操作是帮你创建一个:
bind mount
:创建的永远是一个目录;(--volume
会自动创建,但是--mount
会抛出一个错误)volume
:创建的是一个空的volume
。(--volume
和--mount
都会创建)