3、Docker存储卷基础

容器技术 / 2020-07-24

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。


1、序言

世间万物,皆有其命数!从出生到老去,终归黄土,无人可避!没人拥有灵明石猴的通天本领来篡改生死簿!

你是不是感觉自己萌萌萌哒

​ 咳咳!扯远了!让我们回到Linux

同九教,汝何秀? - 金馆长表情图片大全

Linux上,进程、shell脚本都一样,都有着生命周期,像lsvim命令,运行完进程当即销毁,自动人间蒸发!正如它轻轻地来了,又轻轻地走了。挥一挥衣袖,不带走一片云彩!而使用Docker容器也一样,销毁容器时特别是使用了--rm选项,那么里面产生的数据也将一并销毁!显然,我们不能接受这种情况,因此不能像管理进程、脚本一样来管理容器!

如何解决?在解决问题前,先来了解一个概念!

2、写时复制概念

​ 先来简单回顾一下Docker容器概念,基于特殊的分层叠加文件系统,容器均于只读镜像之上新建一层可写层,专供该容器使用,底层它无权干涉。因为是只读镜像文件,因此镜像里面包含的所有文件,容器里面都可以读到,当需要增删修改时,容器从底层复制该文件到容器上面供容器进行操作,这就是写时复制机制。

​ 好了!既然数据随着容器生命周期结束而结束,那么我们就不应该将数据存放于专属的可写层!想象一下, 能不能跟CPU、内存、磁盘一样,内存充当中介,CPU将数据写入内存缓存,内存再将数据转存至磁盘?

​ 妙哉!妙哉!

​ 当然可以!以后可写层仅充当缓冲区存放临时数据,而后将可写层挂载外部存储空间;数据发生变动时,实时传输至外部存储空间,这样当容器结束其生命周期时,数据因为存放在外部而不受影响,这样就脱离了容器的生命周期,就差一双翅膀就能直接上天!

​ 这就是Docker设计的Data Volume,数据卷;我们国人习惯称之为存储卷!下面是Docker官方的图片:

types of mounts and where they live on the Docker host

CopyRight by@Docker Cloud

3、Data Volume类型:

  • Bind Mount Volume,即将容器存储绑定至宿主机指定的已存在的文件目录

  • Volume,由Docker管理并自动在宿主机和容器生成对应目录,相比bind灵活些。

  • tmpfs mount,只存在于宿主机内存而不会存储到磁盘中,且不会写入容器的可写层,利于提高容器性能。


    好了!关于存储卷概念先说到这,下面开始演示!

4、语法格式

sanxi@container:~$ sudo docker container run --help | grep volume
  -v, --volume list                    Bind mount a volume #指定到宿主机已存在的目录
      --volume-driver string           Optional volume driver for the container
      --volumes-from list              Mount volumes from the specified container(s)

​ 有三个选项,但是官方现在不建议使用-v或者--volume了,我们来使用最新的--mount选项

5、Volume演示

  • 创建与查看volume!顺带提一下,volume是官方推荐的!bind毕竟老东西了!
sanxi@container:/data$ sudo docker volume create my_baby   #先手动创建存储卷
my_baby
sanxi@container:~$ sudo docker volume ls   #看下创建成功没有
DRIVER              VOLUME NAME
local               my_baby
anxi@container:~$ sudo docker container inspect -f {{.Mounts}} bash   #格式化inspect信息,不过挺杂乱的。
[{volume my_baby /var/snap/docker/common/var-lib-docker/volumes/my_baby/_data /test local z true }]
  • 容器内新增文件,然后销毁容器并在宿主机查看是否存在。
#起一个bash容器,新建个文本文件,然后退出自动销毁容器。如果需要只读,在dst后面加个readonly就行。
sanxi@container:~$ sudo docker run --name bash -it --rm --mount src=my_baby,dst=/test bash:latest
bash-5.0# echo "hello,world" > /test/hello.txt
bash-5.0# exit
exit

#查看容器销毁后,宿主机是否还存在此文件。
sanxi@container:~$ sudo cat /var/snap/docker/common/var-lib-docker/volumes/my_baby/_data/hello.txt
hello,world
###双击666,容器被销毁后数据还在!!!

6、Bind Mount Volume演示

  • 先起容器并创建文件,退出销毁容器。
###因为绑定的目录可能比较长,所以我采用的是自定义变量方式
sanxi@container:~$ sudo docker run --name bash -it --rm --mount type=bind,src="$(pwd)/666",dst=/test bash:latest
bash-5.0# cd test/
bash-5.0# echo "sanxi666" > 666.txt
bash-5.0# exit
exit
  • 验证文件是否还存在于bind的目录
sanxi@container:~$ cat 666/666.txt 
sanxi666
###再次双击666!!!

7、tmpfs mount演示

前面说过,tmpfs mount是临时的,仅存活于宿主机的内存中,当容器停止销毁时,tmpfs挂载的临时目录将会被删除且无法保留,也无法在容器间共享。且此功能仅可在==Linux==上运行容器时有效!!!因此仅适合非持久化存储的敏感信息!

  • 先起一个容器,,typetmpfs
sanxi@container:~$ sudo docker run --name=bash -it --rm --mount type=tmpfs,dst=/test bash:latest
[sudo] password for sanxi: 
bash-5.0# 
  • 看一下inspect信息,可以看到并没有存储路径!
sanxi@container:~$ sudo docker container inspect -f {{.Mounts}} bash 
[{tmpfs   /test   true }]
  • 再来看一下存储卷,也是不存在的!因为它是临时的,仅存在于内存而不是存储在磁盘。因此产生的数据在宿主机也是看不到的,一旦退出容器一切都将灰飞烟灭!
sanxi@container:~$ sudo docker volume ls
DRIVER              VOLUME NAME
local               my_baby
local               test8
世间微尘里 独爱茶酒中