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
使用
docker volume
命令对 volume 进行创建、查看和删除。!与此同时,传统的-v
参数创建 volume 的方式也得到了保留。
注:Docker 当前并未对 volume 的大小提供配额管理,用户在创建 volume 时也无法指定 volume 的大小。
容器添加 Volume
使用
docker run
或 docker 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 提供了三种主要的方法来实现宿主机和容器之间的数据挂载:volumes、bind mounts 和 tmpfs mounts。其中,Tmpfs mounts 是将数据存储在宿主机的内存中,不会写入宿主机的文件系统。这种方式适用于不需要持久化存储的数据。volumes、bind mounts 相较之更常用。
使用
docker run
或 docker create
创建新容器时使用 -v
标签为容器添加 volume,可以将自行创建或者由 Docker 创建的 volume 挂载到容器中,也可以将宿主机上的目录或者文件作为 volume 挂载到容器中。下面分别介绍这两种挂载方式:挂载自行创建的 卷
volumes
可使用
--name <volume_name>
标签创建自订名的 volume,并将之挂载到容器中的 /data
目录下。如果用户不执行第一条命令而直接执行第二条命令的话,Docker 会代替用户来创建一个名为 “vol_nginx” 的 volume,并将其挂载到容器中的
/data
目录下。挂载宿主机 目录/文件
bind mounts
- Docker 允许将宿主机上的目录挂载到容器中。
- 必须使用绝对路径,如果宿主机中不存在
/data/docker-volume
,将创建该目录; /data/docker-volume
目录中的所有文件、目录均可在容器/data
目录下被访问;- 若镜像中原本存在
/data
目录,原有的内容将被隐藏,以保持与宿主机目录一致。
e.g. 以下命令将宿主机的/data/docker-volume
目录作为 volume 挂载到容器/data
目录。
注:
- Docker 也可以将单个的文件作为 volume 挂载到容器中。
e.g. 以下命令将主机中的/data/docker-volume/docker-volume.txt
文件作为一个 volume 挂载到容器中的/data/docker-volume.txt
。必须使用绝对路径!
指定挂载权限
挂载多个 Volume
共享 Volume
在使用
docker run
或 docker create
创建新容器时,可以使用 --volumes-from
标签使得容器与已有的容器共享 volume。e.g. 下述新创建容器nginx-02
与之前创建的容器nginx-01
共享同一 volume。
删除 Volume
如果创建容器时从容器中挂载了 volume,在/var/lib/docker/volumes
下会生成与 volume 对应的目录,当使用docker rm
命令删除容器时,对应的目录并不会被删除!!这些目录会占据不必要的存储空间,即使可以手动删除,要查找随机生成、无意义字符的目录名与容器间对应关系也十分麻烦。所以在删除容器时需要对容器的 volume 妥善处理。
在删除容器时一并删除 volume 有两种方法:
- 使用
docker rm -v <container_name>
删除容器。
-
docker run
运行容器时使用--rm
标签,会在容器停止运行时删除容器以及所挂载的卷。
注
- 使用
docker volume rm
删除 volume 时,只在无任何容器使用卷时才能将其成功删除;
- 此两种方法均只会删除未命名的 volume,而对用户指定名字的 volume 进行保留;
- 若 volume 从宿主机中挂载,对容器的任何操作都不会导致其在宿主机中被删除。
Docker CP 命令
Container 与 Host 间复制文件
--volume
vs. --mount
--mount
相较更新,官方推荐
-v
/--volume
由三个字段组成,用冒号 ”:“ 分隔。这些字段必须按照正确的顺序,且每个字段的含义相对不太清晰。
--mount
由多个键值对组成,用逗号 ”,“ 分隔。每个键值对由
<key>=<value>
组成。相较 -v
/ --volume
更冗长,但键的顺序并不重要,更易于理解。- 作者:yomax66
- 链接:https://yomax66.xyz//learning/docker-volume
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。