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/

比如:

运行一个名为 TESTcentos: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 命令,将共享卷的内容同步到指定物理机映射路径的数据卷上,完成备份。

消息盒子

# 暂无消息 #

只显示最新10条未读和已读信息