Docker volume 的几种形态
有状态容器都有数据持久化需求。前一篇文章中提到过,Docker 采用 AFUS 分层文件系统时,文件系统的改动都是发生在最上面的容器层。在容器的生命周期内,它是持续的,包括容器在被停止后。但是,当容器被删除后,该数据层也随之被删除了。因此,Docker 采用 volume (卷)的形式来向容器提供持久化存储。Docker volume 有如下几种形态。
无 - 不使用 Docker volume
默认情况下,容器不使用任何 volume,此时,容器的数据被保存在容器之内,它只在容器的生命周期内存在,会随着容器的被删除而被删除。当然,也可以使用 docker commit 命令将它持久化为一个新的镜像。
Data volume (数据卷)
一个 data volume 是容器中绕过 Union 文件系统的一个特定的目录。它被设计用来保存数据,而不管容器的生命周期。因此,当你删除一个容器时,Docker 肯定不会自动地删除一个volume。有如下几种方式来使用 data volume:
[root@localhost ~]# docker run --name t5 -it -v /data busybox
[root@localhost ~]# docker inspect t5 "Volumes": { "/data": {} }, docker容器内部的目录。 "Mounts": [ { "Type": "volume", "Name": "6c9064deb07520abac42ee42b7931eb9227330f1c209a797b5ef7f035818de26", "Source": "/var/lib/docker/volumes/6c9064deb07520abac42ee42b7931eb9227330f1c209a797b5ef7f035818de26/_data", "Destination": "/data", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ],
"Source": "/var/lib/docker/volumes/6c9064deb07520abac42ee42b7931eb9227330f1c209a797b5ef7f035818de26/_data", #宿主机上的持久化存储目录。
[root@localhost ~]# ls /var/lib/docker/volumes/6c9064deb07520abac42ee42b7931eb9227330f1c209a797b5ef7f035818de26/_data
[root@localhost ~]# cd /var/lib/docker/volumes/6c9064deb07520abac42ee42b7931eb9227330f1c209a797b5ef7f035818de26/_data
其实,在容器被删除后,/var/lib/docker/volumes/6c9064deb07520abac42ee42b7931eb9227330f1c209a797b5ef7f035818de26/_data目录及其中的内容都还会保留下来,但是,新启动的容器无法再使用这个目录,也就是说,已有的数据不能自动地被重复使用了。
绑定的docker_volume目录
[root@localhost _data]# docker run --name t5 -it -v /data/container/t5:/data busybox [root@localhost /]# docker inspect -f {{.Mounts}} t5 [{bind /data/container/t5 /data true rprivate}] [root@localhost t5]# docker inspect -f {{.NetworkSettings.IPAddress}} t5
两个容器挂载同一个宿主机的存储卷
[root@localhost /]# docker run --name t6 -it -v /data/container/t5:/data busybox
[root@localhost /]# docker run --name t7 -it -v /data/container/t5:/data busybox
Docker 新版本中引入了 docker volume 命令来管理 Docker volume。
(1)使用默认的 ‘local’ driver 创建一个 volume
[root@localhost ~]# docker volume create --name vol1 vol1 [root@localhost ~]# docker volume inspect vol1 [ { "CreatedAt": "2019-12-22T21:48:59+08:00", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/vol1/_data", "Name": "vol1", "Options": {}, "Scope": "local" } ]
(2)使用这个 volume
[root@localhost /]# docker run --name t10 -it -v vol1:/webdata12 busybox [root@localhost /]# docker inspect t10 "Mounts": [ { "Type": "volume", "Name": "vol1", "Source": "/var/lib/docker/volumes/vol1/_data", "Destination": "/webdata12", "Driver": "local", "Mode": "z", "RW": true, "Propagation": "" } ],
Volume 删除和孤单 volume 清理
在删除容器时删除 volume
可以使用 docker rm -v 命令在删除容器时删除该容器的卷。
[root@localhost /]# docker run --name t12 -it -v vol1:/webdata14 busybox [root@localhost /]# docker volume ls DRIVER VOLUME NAME local 6c9064deb07520abac42ee42b7931eb9227330f1c209a797b5ef7f035818de26 local 154d9903936e31e74682be4888f359506ca77393e9a89e392d86dfc7fcb2e0b9 local 177a433efe81540ab1301bf9c7581c8496d61d3e1cbc81dd14f3b667215a35f0 local 1228949a934ec83c31dec34e44e070453cf14d90707556675b386146f394cb5f local vol1
[root@localhost /]# docker rm -vf t5 t5 [root@localhost /]# docker volume ls DRIVER VOLUME NAME local 6c9064deb07520abac42ee42b7931eb9227330f1c209a797b5ef7f035818de26 local 154d9903936e31e74682be4888f359506ca77393e9a89e392d86dfc7fcb2e0b9 local 177a433efe81540ab1301bf9c7581c8496d61d3e1cbc81dd14f3b667215a35f0 local 1228949a934ec83c31dec34e44e070453cf14d90707556675b386146f394cb5f local vol1
批量删除孤单 volumes
从上面的介绍可以看出,使用 docker run -v 启动的容器被删除以后,在主机上会遗留下来孤单的卷。可以使用下面的简单方法来做清理:
[root@localhost /]# docker volume ls -qf dangling=true 6c9064deb07520abac42ee42b7931eb9227330f1c209a797b5ef7f035818de26 154d9903936e31e74682be4888f359506ca77393e9a89e392d86dfc7fcb2e0b9 1228949a934ec83c31dec34e44e070453cf14d90707556675b386146f394cb5f [root@localhost /]# docker volume ls DRIVER VOLUME NAME local 6c9064deb07520abac42ee42b7931eb9227330f1c209a797b5ef7f035818de26 local 154d9903936e31e74682be4888f359506ca77393e9a89e392d86dfc7fcb2e0b9 local 177a433efe81540ab1301bf9c7581c8496d61d3e1cbc81dd14f3b667215a35f0 local 1228949a934ec83c31dec34e44e070453cf14d90707556675b386146f394cb5f local vol1 [root@localhost /]# docker volume rm $(docker volume ls -qf dangling=true) 6c9064deb07520abac42ee42b7931eb9227330f1c209a797b5ef7f035818de26 154d9903936e31e74682be4888f359506ca77393e9a89e392d86dfc7fcb2e0b9 1228949a934ec83c31dec34e44e070453cf14d90707556675b386146f394cb5f [root@localhost /]# docker volume ls DRIVER VOLUME NAME local 177a433efe81540ab1301bf9c7581c8496d61d3e1cbc81dd14f3b667215a35f0 local vol1
github 上有很多脚本可以自动化地清理孤单卷,比如:
- https://github.com/chadoe/docker-cleanup-volumes/blob/master/docker-cleanup-volumes.sh
- https://github.com/meltwater/docker-cleanup
1.6 小结
对以上内容的两点小结:
- 容器内的数据是临时性的,它会随着容器生命周期的结束而消失
- 默认的 Docker volume (driver = ‘loclal’)不管是哪种形式,本质上都是将容器所在的主机上的一个目录 mount 到容器内的一个目录,因此,它不具备可移植性。