0 什么是数据卷
docker 的理念之一就是将应用与其运行的环境打包。通常 docker 容器的生命周期都是与在容器中运行的程序相一致的,我们对于数据的要求就是持久化;另一方面 docker 容器之间也需要一个共享文件的渠道。
- 数据卷是经过特殊设计的目录,可以绕过联合文件系统(UFS),为一个或者过个容器提供服务
- 数据卷设计的目的,在于数据的持久化,他完全独立于容器的生存周期,因此,docker 不会在容器删除时删除其挂载的数据卷,也不会存在类似的垃圾收集机制,对容器引用的数据卷进行处理
从图片中:
- 数据卷独立于 docker 容器存在,它存在于 docker 的宿主机中
- 数据卷可以是目录,也可以是文件
- docker 容器可以利用数据卷与宿主机共享文件
- 同一个数据卷可以支持多个容器的访问
1 数据卷的特点
- 数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,这些数据会拷贝到新初始化的数据卷中
- 数据卷可以在容器之间共享和重用
- 可以对数据卷里的内容直接进行修改
- 数据卷的变化不会影响镜像的更新
- 数据卷会一直存在,即使挂载数据卷的容器已经被删除
2 数据卷操作
2.1 添加数据卷
docker run -it -v HOST_DIRECTORY:CONTAINER_DIRETORY IMAGE [COMMADN]
# HOST-DIRECTORY:指定主机目录,不存在时即创建
# CONTAINER:指定容器目录,不存在时即创建
示例:
[root@localhost ~]# docker run -it -v /docker/data_volume:/data_volume busybox /bin/sh
/ # touch /data_volume/test #创建测试文件
/ # echo "lvbibir" > /data_volume/test
/ # cat /data_volume/test
lvbibir
[root@localhost ~]# cat /docker/data_volume/test #验证测试文件
lvbibir
[root@localhost ~]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
be3fad8d789e busybox "/bin/sh" 6 minutes ago Up 6 minutes elastic_boyd
[root@localhost ~]# docker inspect elastic_boyd
2.2 访问权限
docker run -it -v HOST_DIRECTORY:CONTAINER_DIRETORY:r/w IMAGE [COMMADN]
权限可以设置为:
- ro:only-read,只读
- wo:only-write,只写
- rw:write and read,读写
示例:
[root@localhost ~]# docker run -itd -v /docker/data_volume:/data_volume:ro busybox /bin/sh
3ee3a2b7a97c0a10125d46ee1135bf59af1d97932572d49fdd5c0bb64bf775a5
[root@localhost ~]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3ee3a2b7a97c busybox "/bin/sh" 4 seconds ago Up 3 seconds confident_hopper
[root@localhost ~]# docker inspect confident_hopper
2.3 dockerfile
dockerfile 指令:
VOLUME [“HOST_DIRECTORY”]
- dockerfile 中配置数据卷无法指定映射到本地的目录
- 构建好镜像启动容器时,数据卷会进行初始化,docker 会在/var/lib/docker/volumes/下为数据卷创建新的随机名字的目录(不同版本该目录位置可能不同,具体以 inspect 查看到的为准)
- 使用同一个镜像构建的多个容器,映射的本地目录也不一样
- 通过数据卷容器来进行容器间的数据共享
示例:
[root@localhost ~]# cat Dockerfile
#For test data_volume
FROM busybox:latest
VOLUME ["/data_volume1","/data_volume2"]
CMD /bin/sh
[root@localhost ~]# docker build -t test/data_volume .
[root@localhost ~]# docker run -itd --name test_data_volume_1 test/data_volume /bin/sh
ee8347a4bd3590e8cb65a28e1ebfc5d01e44f2ce70d33a2fa9bbc19782e34f21
[root@localhost ~]# docker exec test_data_volume_1 ls -l / | grep data_volume
drwxr-xr-x 2 root root 6 Aug 14 15:20 data_volume1
drwxr-xr-x 2 root root 6 Aug 14 15:20 data_volume2
[root@localhost ~]# docker inspect test_data_volume_1
[root@localhost ~]# docker run -itd --name test_data_volume_2 test/data_volume /bin/sh
b4f654706ea15e657cd61bb92d16fa6c6b8eb9129a68b1c9209ea21967175b24
[root@localhost ~]# docker exec test_data_volume_2 ls -l / | grep data_volume
drwxr-xr-x 2 root root 6 Aug 14 15:24 data_volume1
drwxr-xr-x 2 root root 6 Aug 14 15:24 data_volume2
[root@localhost ~]# docker inspect test_data_volume_2
3 数据卷容器
- 一个命名的容器挂载了数据卷,其他容器通过挂载这个容器实现数据共享,挂载数据卷的容器,就叫做数据卷容器
- 使用数据卷容器而不是用数据卷直接挂载,可以不暴露宿主机的实际目录
- 删除数据卷容器对于已经挂载了该容器的容器没有影响,因为数据卷容器只是传递了挂载信息,任何对于目录的更改都不需要通过数据卷容器
从图片中:
- 数据卷容器挂载了一个本地目录,其他容器通过连接这个数据卷容器来实现数据的共享
3.1 挂载数据卷容器
docker run -it --volumes-from [CONTAINER] IMAGE [COMMAND]
- CONTAINER 必须是已经挂载了卷组的容器,dockerfile 和 -v 两个方式都可以
- CONTAINER 可以未运行,但必须存在
示例:
创建数据卷容器
[root@localhost ~]# cat Dockerfile
#For test data_volume
FROM busybox:latest
VOLUME ["/data_volume1","/data_volume2"]
CMD /bin/sh
[root@localhost ~]# docker build -t test/data_volume .
[root@localhost ~]# docker run -it --name data_volume_container test/data_volume /bin/sh
/ # touch /data_volume1/test1
/ # touch /data_volume2/test2
/ # exit
创建一个容器,挂载数据卷容器进行验证
[root@localhost ~]# docker run -itd --name test_dvc_1 --volumes-from data_volume_container busybox /bin/sh
6c4afa29df7ef226da7f1f0d394a356d53b92e3b20fa6c4632e7197ba393612c
[root@localhost ~]# docker exec test_dvc_1 ls /data_volume1/
test1
[root@localhost ~]# docker exec test_dvc_1 ls /data_volume2/
test2
使用这个新容器对挂载的目录进行更改
[root@localhost ~]# docker exec test_dvc touch /data_volume1/test2
[root@localhost ~]# docker exec test_dvc ls /data_volume1/
test1
test2
再创建一个新容器验证上一个容器对挂载目录的更改是否生效
[root@localhost ~]# docker run -itd --name test_dvc_2 --volumes-from data_volume_container busybox /bin/sh
276c24ecd6ee62f35abf24855ffc5416b9abe987c1bb693ec57bf27d241383d2
[root@localhost ~]# docker exec test_dvc_2 ls /data_volume1
test1
test2
[root@localhost ~]# docker inspect --format="{{.Mounts}}" test_dvc_1
[{volume 1aca4270e7c9ba34b3978638a6bf9e8259c294508207e89b3b9cbb529f4dd4be /var/lib/docker/volumes/1aca4270e7c9ba34b3978638a6bf9e8259c294508207e89b3b9cbb529f4dd4be/_data /data_volume1 local true } {volume d6ebda8735e2c76857d199bd1b96d11c9802d39557d2028bac60f0ec42efc764 /var/lib/docker/volumes/d6ebda8735e2c76857d199bd1b96d11c9802d39557d2028bac60f0ec42efc764/_data /data_volume2 local true }]
[root@localhost ~]# docker inspect --format="{{.Mounts}}" test_dvc_2
[{volume d6ebda8735e2c76857d199bd1b96d11c9802d39557d2028bac60f0ec42efc764 /var/lib/docker/volumes/d6ebda8735e2c76857d199bd1b96d11c9802d39557d2028bac60f0ec42efc764/_data /data_volume2 local true } {volume 1aca4270e7c9ba34b3978638a6bf9e8259c294508207e89b3b9cbb529f4dd4be /var/lib/docker/volumes/1aca4270e7c9ba34b3978638a6bf9e8259c294508207e89b3b9cbb529f4dd4be/_data /data_volume1 local true }]
[root@localhost ~]# docker inspect test_dvc_1
[root@localhost ~]# docker inspect test_dvc_2
3.2 删除数据卷容器
删除数据卷容器后,已经挂载了这个数据卷容器的容器不受任何影响
数据卷容器只传递链接信息,挂载的数据并不需要通过数据卷容器来进行传输
4 数据卷的备份和还原
4.1 数据备份
备份这个数据卷容器挂载的所有目录
docker run --volumes-from [container] -v $(pwd):/backup [image] tar cvf /backup/backup.tar [container data volume]
- -v $(pwd):/backup:挂载一个数据卷用于存放备份文件
- tar 命令:将数据卷容器挂载的目录进行压缩,备份到/backup 目录
4.2 数据还原
docker run --volumes-from [container] -v $(pwd):/backup [image] tar xvf /backup/backup.tar [container data volume]
以上