六、Docker 存储
00 分钟
2024-6-25
2024-7-2
type
status
date
slug
summary
tags
category
icon
password
文章状态
🤔
Docker 的镜像是由一系列的只读层组合而来的。当启动一个容器时,Docker 加载镜像的所有只读层,并在最上层加入一个读写层。这个设计使得 Docker 可以提高镜像构建、存储和分发的效率,节省了时间和存储空间。
然而也造成了如下问题
  • 不能在宿主机上很方便地对容器中的文件进行访问
    • 容器中的文件在宿主机上存在形式复杂
  • 多个容器之间的数据无法共享
  • 当删除容器时,容器产生的数据将丢失
为了解决上述问题,Docker 引入了 数据卷(volume)机制

什么是 Volume ?

Volume 是存在于一个或多个容器中的特定文件或文件夹。
这个目录以独立于联合文件系统的形式在宿主机中存在,并为数据的共享与持久化提供以下便利
  • volume 在容器创建时就会初始化,在容器运行时就可以使用其中的文件;
  • volume 能在不同的容器之间共享和重用
  • 对 volume 中数据的操作会马上生效
  • 对 volume 中数据的操作不会影响到镜像本身
  • volume 的生存周期独立于容器的生存周期
    • 即使删除容器,volume 仍然会存在。没有任何容器使用的 volume 也不会被删除。
为容器添加 volume,类似于 Linux 中的 mount 操作——用户将一个文件夹作为 volume 挂载到容器上,可以很方便地将数据添加到容器中供其中的进程使用。多个容器可以共享同一个 volume,为不同容器之间的数据共享提供了便利。
为容器添加 volume,类似于 Linux 中的 mount 操作——用户将一个文件夹作为 volume 挂载到容器上,可以很方便地将数据添加到容器中供其中的进程使用。多个容器可以共享同一个 volume,为不同容器之间的数据共享提供了便利。

创建 Volume

使用 docker volume 命令对 volume 进行创建、查看和删除。
!与此同时,传统的 -v 参数创建 volume 的方式也得到了保留。
注:Docker 当前并未对 volume 的大小提供配额管理,用户在创建 volume 时也无法指定 volume 的大小。
注:Docker 当前并未对 volume 的大小提供配额管理,用户在创建 volume 时也无法指定 volume 的大小。

容器添加 Volume

使用 docker rundocker create 创建新容器时,也可以使用 -v 标签为容器添加 volume。
  • 匿名卷
    • 以下命令创建了一个随机名字的 volume,并挂载到容器中的/data目录下。
  • 自订名称的卷
    • 以下命令创建了一个指定名字的 volume,并挂载到容器中的 /data 目录下。

Dockerfile 中创建 Volume

在 Dockerfile 中使用 VOLUME 指令可向容器添加 volume。
在使用 docker build 命令生成镜像并且以该镜像启动容器时,此指令会挂载一个 volume 到 /data 目录下。即等同于使用了 docker run -v /data 命令。

Volume 存储路径

Docker 在创建 volume 的时候会在宿主机 /var/lib/docker/volumes/ 目录下创建一个以 volume ID 为名的目录,并将 volume 中的内容存储在名为 _data 的目录下。
使用 docker volume inspect 命令可以获得该 volume 包括其在宿主机中该文件夹的位置等信息。

挂载 Volume

Docker 提供了三种主要的方法来实现宿主机和容器之间的数据挂载:volumesbind mountstmpfs mounts。其中,Tmpfs mounts 是将数据存储在宿主机的内存中,不会写入宿主机的文件系统。这种方式适用于不需要持久化存储的数据。volumesbind mounts 相较之更常用。
使用 docker rundocker create 创建新容器时使用 -v 标签为容器添加 volume,可以将自行创建或者由 Docker 创建的 volume 挂载到容器中,也可以将宿主机上的目录或者文件作为 volume 挂载到容器中。下面分别介绍这两种挂载方式:
挂载自行创建的 卷
volumes
可使用 --name <volume_name> 标签创建自订名的 volume,并将之挂载到容器中的 /data 目录下。
如果用户不执行第一条命令而直接执行第二条命令的话,Docker 会代替用户来创建一个名为 “vol_nginx” 的 volume,并将其挂载到容器中的 /data 目录下。
如果用户不执行第一条命令而直接执行第二条命令的话,Docker 会代替用户来创建一个名为 “vol_nginx” 的 volume,并将其挂载到容器中的 /data 目录下。
挂载宿主机 目录/文件
bind mounts
  • Docker 允许将宿主机上的目录挂载到容器中。
    • e.g. 以下命令将宿主机的 /data/docker-volume 目录作为 volume 挂载到容器 /data 目录。
      注:
      注:
      • 必须使用绝对路径,如果宿主机中不存在 /data/docker-volume,将创建该目录;
      • /data/docker-volume 目录中的所有文件、目录均可在容器 /data 目录下被访问;
      • 若镜像中原本存在 /data 目录,原有的内容将被隐藏,以保持与宿主机目录一致。
  • Docker 也可以将单个的文件作为 volume 挂载到容器中。
    • e.g. 以下命令将主机中的 /data/docker-volume/docker-volume.txt 文件作为一个 volume 挂载到容器中的 /data/docker-volume.txt 必须使用绝对路径!
指定挂载权限
挂载多个 Volume

共享 Volume

在使用 docker rundocker create 创建新容器时,可以使用 --volumes-from 标签使得容器与已有的容器共享 volume。
e.g. 下述新创建容器 nginx-02 与之前创建的容器 nginx-01 共享同一 volume。

删除 Volume

如果创建容器时从容器中挂载了 volume,在 /var/lib/docker/volumes 下会生成与 volume 对应的目录,当使用 docker rm 命令删除容器时,对应的目录并不会被删除!!这些目录会占据不必要的存储空间,即使可以手动删除,要查找随机生成、无意义字符的目录名与容器间对应关系也十分麻烦。所以在删除容器时需要对容器的 volume 妥善处理。
在删除容器时一并删除 volume 有两种方法:
  1. 使用 docker rm -v <container_name> 删除容器。
  1. docker run 运行容器时使用 --rm 标签,会在容器停止运行时删除容器以及所挂载的卷。
注
  1. 使用 docker volume rm 删除 volume 时,只在无任何容器使用卷时才能将其成功删除;
  1. 此两种方法均只会删除未命名的 volume,而对用户指定名字的 volume 进行保留;
  1. 若 volume 从宿主机中挂载,对容器的任何操作都不会导致其在宿主机中被删除。

Docker CP 命令

Container 与 Host 间复制文件

--volume vs. --mount

--mount 相较更新,官方推荐
  • -v / --volume
    • 由三个字段组成,用冒号 ”:“ 分隔。这些字段必须按照正确的顺序,且每个字段的含义相对不太清晰。
  • --mount
    • 由多个键值对组成,用逗号 ”,“ 分隔。每个键值对由 <key>=<value> 组成。相较 -v / --volume 更冗长,但键的顺序并不重要,更易于理解。
 
上一篇
七、Docker 资源限制
下一篇
云计算