Docker Volume 的那点事
使用 docker 的过程中,数据保存是很重要的一环,因为容器一旦被删除,容器内的数据也将一并被删除。而 Volume 正是为了解决这个问题而存在,它可以映射一个物理机上的文件夹到容器内部,用于保存容器产生的数据。下面就来说说 Dokcer Volume 的使用及注意事项。
数据卷特性
Volume 也称 Data Volume
,是一种数据卷的形式,它是供一个或多个容器使用的文件或目录,有以下特性:
- 可以共享于多个容器之间;
- 对数据卷的修改会立即生效;
- 对数据卷的更新与镜像无关;
- 数据卷会一直存在直到手动清除。
使用数据卷
[hzz@magedu ~]$ docker run --help
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Run a command in a new container
Options:
...
-v, --volume value Bind mount a volume (default [])
--volume-driver string Optional volume driver for the container
--volumes-from value Mount volumes from the specified container(s) (default [])
...
[hzz@magedu ~]$
从 docker run
的帮助命令中可以看到,Volume
是其中的一个参数,也就是说数据卷需要在容器启动时进行配置并生效。
使用数据卷有如下几种方式:
方式一:docker run -v /MOUNT_POINT
这种是使用默认物理主机路径进行映射,默认的映射路径为:
/var/lib/docker/volumes/
比如:
运行一个名为 TEST
的 centos:7
容器,使用默认路径映射到容器内的 /root
中,并创建 test_volume
文件。
[root@magedu ~]# docker run -v /root --name TEST centos:7 touch /root/test_volume
[root@magedu ~]# ls -l /var/lib/docker/volumes/c0201a28a899477ada1f62d32de8dc1aa58ca93be5e7a708dbb5ae53c082066b/_data/
总用量 4
-rw-------. 1 root root 3270 3月 2 09:07 anaconda-ks.cfg
-rw-r--r--. 1 root root 0 3月 8 00:56 test_volume
[root@magedu ~]#
可以看到,在 /var/lib/docker/volumes/
的某文件夹内(名称是随机的),也创建了同样的 test_volume
文件。可以证明这个文件夹与容器内的 /root
是相互映射的。只要不去执行删除卷的操作(后面会说到),则容器内 /root
里面的内容是永久保存在物理机上的。
但是这种方式带来一个问题,就是由于默认路径下,物理机上的文件夹命名是随机的,当需要映射数据卷的容器增多时,很难能找到某个容器映射的数据卷所在的物理路径,对于数据提取及备份来说,很是麻烦。所以一般来说建议使用第二种方式。
方式二:docker run -v /HOST/DIR:/CONTAINER/DIR
这种方式使用指定物理机上的某个路径,与容器中的某个路径进行映射,这样就能明确地知道容器中映射的是哪个物理路径,便于数据提取及备份。
比如:
还是跟前一个例子类似,只是我们将容器内 /root
映射到物理机的 /root
中来看看效果。
[root@magedu ~]# ls -l /root
总用量 4
-rw-------. 1 root root 1412 3月 7 15:28 anaconda-ks.cfg
[root@magedu ~]# docker run -v /root:/root --name TEST centos:7 touch /root/test_volume
[root@magedu ~]# ls -l /root
总用量 4
-rw-------. 1 root root 1412 3月 7 15:28 anaconda-ks.cfg
-rw-r--r--. 1 root root 0 3月 8 01:30 test_volume
[root@magedu ~]#
可以看到,物理机上 /root
中出现了容器所创建的 test_volume
文件,说明映射成功。
容器之间共享卷
数据卷不单可以将容器内的文件夹映射到物理机,还可以实现多个容器共用同一个物理文件夹。
方式一:映射同一个文件夹
可以将两个容器运行时,指定同一个物理机文件夹作为数据卷使用。
[root@magedu ~]# ls -l
总用量 4
-rw-------. 1 root root 1412 3月 7 15:28 anaconda-ks.cfg
[root@magedu ~]# docker run -v /root:/root --name TEST6 centos:6 touch /root/test_volume_6
[root@magedu ~]# docker run -v /root:/root --name TEST7 centos:7 ls -l /root/
total 4
-rw-------. 1 root root 1412 Mar 7 07:28 anaconda-ks.cfg
-rw-r--r--. 1 root root 0 Mar 7 18:05 test_volume_6
[root@magedu ~]# ls -l
总用量 4
-rw-------. 1 root root 1412 3月 7 15:28 anaconda-ks.cfg
-rw-r--r--. 1 root root 0 3月 8 02:05 test_volume_6
[root@magedu ~]#
可以看到,我用 TEST6
容器创建的 /root/test_volume_6
文件,可以同时在 TEST7
容器及物理机中看到,说明两个容器的数据卷都同时映射到了物理机的同一个目录,实现了数据共享。
方式二:使用 --volumes-from value
参数
如果前一个容器使用的是默认挂载的方式(不指定物理路径),那两个容器间要想实现数据共享,用方式一就比较麻烦了,毕竟得先找出前一个容器数据卷的物理机路径。
这时候就需要用到 docker run
自带的参数了。
[root@magedu ~]# docker run -v /root --name TEST6 centos:6 touch /root/test_volume_6
[root@magedu ~]# docker run --volumes-from TEST6 --name TEST7 centos:7 ls -l /root/
total 16
-rw-------. 1 root root 2654 Mar 2 04:44 anaconda-ks.cfg
-rw-r--r--. 1 root root 7307 Mar 2 04:44 install.log
-rw-r--r--. 1 root root 1680 Mar 2 04:44 install.log.syslog
-rw-r--r--. 1 root root 0 Mar 7 18:28 test_volume_6
[root@magedu ~]#
可以看到,容器 TEST6
和容器 TEST7
实现了 /root
路径的共享,并且无需知道所映射的物理路径。
删除卷
要删除数据卷也有两种方式。
第一种是在删除容器时,将数据卷一起删掉:
docker rm -v CONTAINER_NAME;
第二种是在运行容器时,加上 --rm
选项,这样表示容器关闭会被自动删除,同时删除其卷:
docker run --rm ...
需要注意的是,以上两种删除方式的前提是,此容器为最后一个使用此卷的容器,也就是说,如果卷是共享的,则删除卷的前提是没有容器在使用此卷。
当然,还有第三种非官方的方式,就是在删除容器后,找到数据卷所映射的物理机路径,手动进行删除。在使用指定物理机映射路径的情况下,建议使用这种方式,避免误操作导致数据丢失。
备份和恢复
既然有误删数据的风险,那是否有备份机制呢?
当然还是有的,想想看,既然都知道物理机路径了,该咋备份还不明白吗?
crontab+tar
走起,嘿嘿。
当然以上方式针对于指定物理机映射路径的容器来说比较方便。对于使用默认路径映射的容器,能否找到物理机映射路径还是个问题。那这种容器是否有快捷的备份方式呢?
方法还是有的,那就是使用另一个指定物理机映射路径的容器,通过与原容器共享卷来进行备份,如下:
[hzz@magedu ~]$ docker run -v /data --name CentOS6 centos:6 touch /data/test_volume6
[hzz@magedu ~]$ docker run --volumes-from CentOS6 -v $(pwd):/CentOS6_Backup busybox:latest tar cvf /CentOS6_Backup/backup.tar /data
tar: removing leading '/' from member names
data/
data/test_volume6
[hzz@magedu ~]$ tar xvf backup.tar
data/
data/test_volume6
[hzz@magedu ~]$ ls -l data/
总用量 0
-rw-r--r--. 1 hzz hzz 0 3月 8 03:34 test_volume6
[hzz@magedu ~]$
容器 CentOS6
是没有指定物理机映射路径的,但我们可以再开启一个指定物理机映射路径的 busybox
容器,并使其与 CentOS6
容器共享卷,然后通过 tar
命令,将共享卷的内容同步到指定物理机映射路径的数据卷上,完成备份。