前言
容器中进行数据管理主要有两种方式:
- 数据卷(Data Volumes):容器内数据直接映射到本地主机内。
- 数据卷容器(Data Volume Containers):由专门特定的容器进行数据管理和维护。
创建数据卷
docker volume create -d local [VOLUME NAME]
除了 create
子命令外, docker volume
还有 inspect
、 ls
、 prune
(删除所有未使用的本地卷) 、 rm
等,更多更详细信息请参考 docker volume 。
绑定数据卷
除了使用 volume
子命令来管理数据卷外,还可以在创建容器时将主机本地的任意路径挂载到容器内作为数据卷,这种形式创建的数据卷称为绑定数据卷。
在使用 docker run
命令的时候,可使用 -v
( --volume
)或者 --mount
将主机本地的 任意数据挂在到容器内作为数据卷。
一般来说,--mount
更明确和详细。最大的区别是-v
语法将所有选项组合在一个字段中,而--mount
语法将它们分开。所以,Docker 官方教程中表明:
新用户应使用
--mount
语法。有经验的用户可能更熟悉-v
or--volume
语法,但鼓励使用--mount
,因为研究表明它更易于使用。
区别
如果你使用 -v
或--volume
来绑定挂载一个在 Docker 主机上还不存在的文件或目录, -v
会为你创建端点。它总是被创建为一个目录。
如果你使用 --mount
来绑定挂载一个在 Docker 主机上还不存在的文件或目录, Docker 不会自动为你创建它,而是生成一个错误。
-v
或 -–volume
由三个字段组成,以冒号(:)分隔。这些字段必须以正确的顺序排列,并且每个字段的含义不是立即显而易见的。
-
在绑定挂载的情况下,第一个字段是主机上文件或目录的路径。
-
第二个字段是文件或目录在容器中挂载的路径。
-
第三个字段是可选的,并且是用逗号分隔的选项,诸如列表
ro
,z
和Z
,默认为rw
。加了
ro
后,容器内对数据卷中的数据就无法修改了。
示例:
-v /mnt/USB64G/owncloud/data/Yogile/files:/share/Yogile:rw
--mount
由多个键值对组成,用逗号隔开,每个键值对由一个 <key>=<value>
元组组成。 --mount
的语法比 -v
或 --volume
更冗长,但是键的顺序并不重要,而且标志的值更容易理解。
-
挂载的
type
,可以是bind
、volume
或tmpfs
,如果不指定type
选项,则默认为挂载volume
。bind
:绑定数据卷,映射到主机指定路径下。volume
:普通数据卷,映射到主机/var/lib/docker/volumes
路径下。tmpfs
:临时数据卷,只存在于内存中。注意:当
type
为volume
时,source
只能命名为符合[a-zA-Z0-9][a-zA-Z0-9_.-]
的规则,此时必须映射到主机/var/lib/docker/volumes
路径下,否则报错:docker: Error response from daemon: create /home/docker_start/backup/backup: "/home/docker_start/backup/backup" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed. If you intended to pass a host directory, use absolute path. See 'docker run --help'.
-
挂载的
source
。对于绑定挂载,这是 Docker 守护程序主机上文件或目录的路径。可以指定为source
或src
。 -
destination
的值是文件或目录在容器中被挂载的路径。可以指定为destination
,dst
或target
。 -
如果存在
readonly
选项,会使绑定挂载被以只读方式挂载到容器中。不存在该选项,则是读写权限。 -
如果存在
bind-propagation
选项,则改变绑定传播。可以是rprivate
,private
,rshared
、shared
、rslave
、slave
之一。 -
--mount
标志不支持z
或Z
选项来修改selinux
标签。
示例:
--mount source=blc-data,target=/blivechat/data # 实际上为: --mount type=volume,source=blc-data,target=/blivechat/data ## 查看数据卷信息 $ docker volume inspect blc-data [ { "CreatedAt": "2021-07-06T16:21:01+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/blc-data/_data", "Name": "blc-data", "Options": null, "Scope": "local" } ]
数据卷容器
若用户需要在多个容器之间共享一类数据,可以使用数据卷容器。数据卷容器也是容器,但其目的是为了专门给其他容器提供挂载的数据卷。
步骤:
-
创建数据卷容器(下文称为 OriginContainer)。
docker run -it --mount [OPTIONS] --name [CONTAINER NAME] [USER]/[IMAGE NAME]:[TAG]
示例:
docker run -it --mount type=volume,source=data-more,target=/data-more --name OriginContainer ubuntu:18.04
-
在其他容器中使用
--volumes-from
来继承 OriginContainer 容器的数据卷。docker run -it --volumes-from [OriginContainer NAME] --name [CONTAINER NAME] [USER]/[IMAGE NAME]:[TAG]
多个容器都挂载 OriginContainer 容器的数据卷,任何一个对数据卷的内容进行更改,其他所有容器都会看到。
还可以使用
--volumes-from
来继承容器的继承。注意:
-
使用
--volumes-from
所挂载数据卷的 OriginContainer 容器自身并不一定需要保持在运行状态。 -
删除了挂载数据卷的 OriginContainer 容器以及继承 OriginContainer 的其他所有容器,数据卷并不会自动删除。
-
要删除数据卷,必须显式地使用
docker rm -v
命令来指定同时删除与该数据卷关联的容器。docker rm -v [CONTAINER NAME]
-
利用数据卷容器来迁移数据卷
备份
备份时推荐使用 -v
来进行指定数据卷为主机具体目录。
docker run --volumes-from [CONTAINER NAME] --mount type=volume,source=[VOLUMES GOAL PATH],target=[BACKUP PATH] --name [NEW CONTAINER NAME] [USER]/[IMAGE NAME]:[TAG] tar cvf [BACKUP FILEPATH] [CONTAINER VOLUME PATH]
分析命令:
- 创建新容器
[NEW CONTAINER NAME]
并继承[CONTAINER NAME]
挂载的数据卷;--mount
将主机[VOLUMES GOAL PATH]
目录挂载到[NEW CONTAINER NAME]
的[BACKUP PATH]
目录;[NEW CONTAINER NAME]
启动后,会使用tar cvf
将[CONTAINER VOLUME PATH]
的内容备份为[BACKUP FILEPATH]
,即[VOLUMES GOAL PATH]
目录下的文件。
注意:前文提到,当 type
为 volume
时, source
只能命名为符合 [a-zA-Z0-9][a-zA-Z0-9_.-]
的规则,此时必须映射到主机 /var/lib/docker/volumes
路径下。如果需要另指定数据卷为主机具体目录,则应该用 -v
或 --volume
。
docker run --volumes-from [CONTAINER NAME]
--volume [GOAL PATH]:[BACKUP PATH]
--name [NEW CONTAINER NAME] [USER]/[IMAGE NAME]:[TAG]
tar cvf [BACKUP FILEPATH] [CONTAINER VOLUME PATH]
示例:
# --mount docker run --volumes-from OriginContainer --mount type=volume,source=backup,target=/backup --name BackupContainer ubuntu:18.04 tar cvf /backup/backup-data-more.tar /data-more # --volume 推荐 docker run --volumes-from OriginContainer --volume /home/docker_start/backup/backup:/backup --name BackupContainer ubuntu:18.04 tar cvf /backup/backup-data-more.tar /data-more
还原
-
创建一个带有数据卷的容器,对于数据卷的配置应与备份的原容器数据卷相同。
示例:
docker run --mount type=volume,source=data-more,target=/data-more --name TempContainer ubuntu:18.04 /bin/bash
-
创建一个新容器,继承 NewContainer 容器挂载的数据卷,并使用 untar 解压备份文件到所挂载的容器中。
docker run --volumes-from [TempContainer NAME] --mount type=volume,source=[FROM PATH],target=[BACKUP PATH] --name [NEWCONTAINER NAME] [USER]/[IMAGE NAME]:[TAG] tar xvf [CONTAINER BACKUP FILEPATH]
示例:
docker run --volumes-from TempContainer --mount type=volume,source=$(pwd)/backup,target=/backup --name NewContainer ubuntu:18.04 tar xvf /backup/backup-data-more.tar
注意:只要指定的数据卷配置与备份的原容器数据卷相同,还原到 NewContainer 容器的压缩包,经过 untar 解压、 Docker 还原后,会恢复到初始数据卷中。请参阅后面演示部分。
演示
创建起源容器
[root@iZbp1ghdm1cpgzasefxqxnZ ~]# docker run -it --mount type=volume,source=data-more,target=/data-more
> --name OriginContainer ubuntu:18.04
Unable to find image 'ubuntu:18.04' locally
18.04: Pulling from library/ubuntu
25fa05cd42bd: Pull complete
Digest: sha256:139b3846cee2e63de9ced83cee7023a2d95763ee2573e5b0ab6dea9dfbd4db8f
Status: Downloaded newer image for ubuntu:18.04
root@bcdd9429f4db:/# ls
bin boot data-more dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@bcdd9429f4db:/# cd /data-more/
root@bcdd9429f4db:/data-more# echo "echo "Yogile"" >> echo-Yogile.sh
root@bcdd9429f4db:/data-more# chmod +x echo-Yogile.sh
root@bcdd9429f4db:/data-more# ./echo-Yogile.sh
Yogile
root@bcdd9429f4db:/data-more# exit
exit
[root@iZbp1ghdm1cpgzasefxqxnZ ~]#
备份
# -v 另指定数据卷为主机具体目录
[root@iZbp1ghdm1cpgzasefxqxnZ ~]# docker run --volumes-from OriginContainer
> -v /home/docker_start/backup/backup:/backup
> --name BackupContainer ubuntu:18.04
> tar cvf /backup/backup-data-more.tar /data-more
tar: Removing leading `/' from member names
/data-more/
/data-more/echo-Yogile.sh
[root@iZbp1ghdm1cpgzasefxqxnZ ~]# ls /home/docker_start/backup/backup
backup-data-more.tar
[root@iZbp1ghdm1cpgzasefxqxnZ ~]#
还原
为进行还原,将 OriginContainer 容器、 BackupContainer 容器以及 data-more 数据卷删除。
# 删除容器
[root@iZbp1ghdm1cpgzasefxqxnZ ~]# docker rm BackupContainer
BackupContainer
[root@iZbp1ghdm1cpgzasefxqxnZ ~]# docker rm OriginContainer
OriginContainer
# 删除数据卷
[root@iZbp1ghdm1cpgzasefxqxnZ ~]# docker volume rm data-more
data-more
[root@iZbp1ghdm1cpgzasefxqxnZ ~]# /var/lib/docker/volumes/data-more/_data/echo-Yogile.sh
-bash: /var/lib/docker/volumes/data-more/_data/echo-Yogile.sh: No such file or directory
接下来进行还原
# 创建一个带有数据卷的容器,对于数据卷的配置应与备份的原容器数据卷相同
[root@iZbp1ghdm1cpgzasefxqxnZ ~]# docker run --mount type=volume,source=data-more,target=/data-more
> --name TempContainer ubuntu:18.04 /bin/bash
# 继承 NewContainer 容器挂载的数据卷,并使用 untar 解压备份文件到所挂载的容器中
[root@iZbp1ghdm1cpgzasefxqxnZ ~]# docker run --volumes-from TempContainer
> -v /home/docker_start/backup/backup:/backup
> --name NewContainer ubuntu:18.04
> tar xvf /backup/backup-data-more.tar
data-more/
data-more/echo-Yogile.sh
[root@iZbp1ghdm1cpgzasefxqxnZ ~]# /var/lib/docker/volumes/data-more/_data/echo-Yogile.sh
Yogile