本文已参与「新人创作礼」活动,一起开启掘金创作之路。
叙述
数据存储介绍: docs.docker.com/storage/
为什么要持久化?
- 默认情况下,在容器内创建的所有文件都存储在可写容器层上。容器不存在时,数据不会持续存在。
- 容器的可写层与运行容器的主机紧密耦合。您无法轻松地将数据移动到其他地方
- 写入容器的可写层需要 存储驱动程序来管理文件系统。存储驱动程序提供了一个联合文件系统,使用 Linux 内核。与使用直接写入主机文件系统的数据卷相比,这种额外的抽象会降低性能
持久化2种方法
volume、bind mount
挂载类型
named pipes(命名管道)
- pipes挂载可用于 Docker 主机和容器之间的通信。
- 常见用例是在容器内运行第三方工具并使用命名管道连接到 Docker Engine API
tmpfs mounts
- tmpfs mounts不会持久保存在磁盘上。它可以在容器的生命周期内被容器使用,用于存储非持久状态或敏感信息
- 例如,在内部swarm服务使用tmpfs mounts将秘密挂载到服务的容器中。
- 使用参数: --tmpfs
volumes(卷)
- Docker创建和管理。非 Docker 进程不应修改文件系统的这一部分。卷是在 Docker 中持久化数据的最佳方式
- 卷存储在Docker主机/var/lib/docker/volumes/。将卷挂载到容器中时,此目录就是挂载到容器中的目录。这类似于绑定挂载的工作方式,只是卷 由Docker管理并且与主机的核心功能隔离。
- 卷可以共享到多个容器中,当没有正在运行的容器使用卷时,卷仍然可供 Docker 使用,并且不会自动删除
- 当挂载一个卷时,它可能是命名的或匿名的。匿名卷在首次挂载到容器时没有明确的名称,Docker为它提供了一个随机名称,该名称保证在给定的 Docker 主机中是唯一的。除了名称之外,命名卷和匿名卷的行为方式相同
- 卷还支持使用卷驱动程序,它允许您将数据存储在远程主机或云提供商上,以及其他可能性
示例
docker volume create --name testvolume # 创建一个volume
docker volume inspect testvolume # 查看volume详情
docker volume ls
testvolume挂载到容器中的/mydata目录
docker run -it -v testvolume:/mydata alpine sh
--volume,-v: 挂载
testvolume挂载到服务中
docker service create --replicas 2 --mount type=volume,src=testvolume,dst=/mydata --name test_nginx nginx
type: 挂载类型
src: 源目录,参数名也可以写成source
dst: 容器内的路径,参数名也可以写成target
与bind mount不同
- 如果volume目录是空的而容器中的目录有内容,docker会将容器目录中的内容拷贝到volume中;
- 如果volumes中已经有内容,则会将容器中的目录覆盖
bind mounts(绑定挂载)
- 与卷相比,绑定挂载的功能有限。使用绑定挂载时,主机上的文件或目录会挂载到容器中。文件或目录由其在主机上的完整路径引用。该文件或目录不需要已经存在于 Docker 主机上。如果它尚不存在,则按需创建。
- 绑定挂载非常高效,但它们依赖于具有特定目录结构的主机文件系统。如果您正在开发新的 Docker 应用程序,请考虑改用命名卷。您不能使用 Docker CLI 命令直接管理绑定挂载
- 绑定挂载允许访问敏感文件,无论好坏,使用绑定挂载的一个副作用是,您可以通过在容器中运行的进程更改主机文件系统 ,包括创建、修改或删除重要的系统文件或目录。这是一种强大的能力,可能会产生安全隐患,包括影响主机系统上的非 Docker 进程。
- bind mount在不同的宿主机系统时不可移植的,比如Windows和Linux的目录结构是不一样的,bind mount所指向的host目录也不能一样。
- 这也是为什么bind mount不能出现在Dockerfile中的原因,因为这样Dockerfile就不可移植了
示例
主机data目录,挂载到容器中的/container-data目录
docker run -it -v /test/data:/container-data alpine sh
--volume,-v: 挂载
挂载本地目录方法
docker service create --mount type=bind,target=/container_data/,source=/host_data/
type: 挂载类型
target: 容器里面的路径
source: 本地硬盘路径, 需要存在
注意
- 主机的目录路径必须为全路径
- 如果主机的目录不存在,docker会自动在主机上创建该目录
- 如果容器中的目录不存在,docker会自动创建该目录
- 如果容器中的目录已经有内容,那么docker会使用主机data目录将其覆盖掉
建议
对于绑定装载、卷或tmpfs装载,建议对容器和服务使用参数 --mount,因为语法更清晰