docker之数据持久化

457 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

叙述

数据存储介绍: docs.docker.com/storage/

为什么要持久化?

  1. 默认情况下,在容器内创建的所有文件都存储在可写容器层上。容器不存在时,数据不会持续存在。
  2. 容器的可写层与运行容器的主机紧密耦合。您无法轻松地将数据移动到其他地方
  3. 写入容器的可写层需要 存储驱动程序来管理文件系统。存储驱动程序提供了一个联合文件系统,使用 Linux 内核。与使用直接写入主机文件系统的数据卷相比,这种额外的抽象会降低性能

持久化2种方法

volume、bind mount

挂载类型

named pipes(命名管道)

  1. pipes挂载可用于 Docker 主机和容器之间的通信。
  2. 常见用例是在容器内运行第三方工具并使用命名管道连接到 Docker Engine API

tmpfs mounts

  1. tmpfs mounts不会持久保存在磁盘上。它可以在容器的生命周期内被容器使用,用于存储非持久状态或敏感信息
  2. 例如,在内部swarm服务使用tmpfs mounts将秘密挂载到服务的容器中。
  3. 使用参数: --tmpfs

volumes(卷)

  1. Docker创建和管理。非 Docker 进程不应修改文件系统的这一部分。卷是在 Docker 中持久化数据的最佳方式
  2. 卷存储在Docker主机/var/lib/docker/volumes/。将卷挂载到容器中时,此目录就是挂载到容器中的目录。这类似于绑定挂载的工作方式,只是卷 由Docker管理并且与主机的核心功能隔离。
  3. 卷可以共享到多个容器中,当没有正在运行的容器使用卷时,卷仍然可供 Docker 使用,并且不会自动删除
  4. 当挂载一个卷时,它可能是命名的或匿名的。匿名卷在首次挂载到容器时没有明确的名称,Docker为它提供了一个随机名称,该名称保证在给定的 Docker 主机中是唯一的。除了名称之外,命名卷和匿名卷的行为方式相同
  5. 卷还支持使用卷驱动程序,它允许您将数据存储在远程主机或云提供商上,以及其他可能性

示例

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不同

  1. 如果volume目录是空的而容器中的目录有内容,docker会将容器目录中的内容拷贝到volume中;
  2. 如果volumes中已经有内容,则会将容器中的目录覆盖

bind mounts(绑定挂载)

  1. 与卷相比,绑定挂载的功能有限。使用绑定挂载时,主机上的文件或目录会挂载到容器中。文件或目录由其在主机上的完整路径引用。该文件或目录不需要已经存在于 Docker 主机上。如果它尚不存在,则按需创建。
  2. 绑定挂载非常高效,但它们依赖于具有特定目录结构的主机文件系统。如果您正在开发新的 Docker 应用程序,请考虑改用命名卷。您不能使用 Docker CLI 命令直接管理绑定挂载
  3. 绑定挂载允许访问敏感文件,无论好坏,使用绑定挂载的一个副作用是,您可以通过在容器中运行的进程更改主机文件系统 ,包括创建、修改或删除重要的系统文件或目录。这是一种强大的能力,可能会产生安全隐患,包括影响主机系统上的非 Docker 进程。
  4. bind mount在不同的宿主机系统时不可移植的,比如Windows和Linux的目录结构是不一样的,bind mount所指向的host目录也不能一样。
  5. 这也是为什么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: 本地硬盘路径, 需要存在

注意

  1. 主机的目录路径必须为全路径
  2. 如果主机的目录不存在,docker会自动在主机上创建该目录
  3. 如果容器中的目录不存在,docker会自动创建该目录
  4. 如果容器中的目录已经有内容,那么docker会使用主机data目录将其覆盖掉

建议

对于绑定装载、卷或tmpfs装载,建议对容器和服务使用参数 --mount,因为语法更清晰