Docker提供两种数据存储资源,一种是基于storage driver提供的镜像层和容器层,一种是基于data volume提供的持久化存储。

Docker_Storage

图1 Docker存储框架

图1 描述了Docker存储的整体框架,它主要支持两种类型存储,一种是storage driver管理的镜像层与容器层,对现有容器数据的读写;一种是data volume持久化存储,提供bind volumedocker managed volume存储。

Storage driver

我们知道容器镜像是按照多个层级来分层叠加的,如下图2示意,容器包含最上层的读写层与下面多个只读镜像层,当需要修改容器数据的时候,会将只读层数据COPY至容器层进行修改,修改后数据保存在容器层,镜像层不变,即使用了linux的Copy on write特性。

docker-container-images

图2 存储:镜像层与容器层-图片出自网络

这种数据存储的生命周期当然会随着容器的销毁而结束,如果想在容器销毁后依然保存数据,该怎么办呢,答案是持久化存储-data volume

Data volume

Data volume提供两种类型存储。一种是bind volume,另一种是docker managed volume。前者简单理解就是将host主机目录共享给容器,容器注销了主机还在,所以数据当然不会丢失(除非主机故障或者数据丢失)。后者也是挂载主机目录到容器,不过是隐形挂载。举几个示例简单说明。

  1. 使用-v [host path]:/[container path]进行bind volume显示挂载

    • /root/test目录下新建了一个test.txt文档
    1
    2
    3
    4
    $sudo pwd
    /root/test
    $sudo ls
    test.txt
    • 使用显示挂载将其隐射给容器
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $sudo docker run -it -d -v /root/test:/usr/home/test alpine:x86-3.11.5 
    adc809b503883f6cd91f30343a721c12a915e7cdb79ed1197d677bc705c23160
    $sudo docker ps -a
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    adc809b50388 alpine:x86-3.11.5 "/bin/sh" 14 seconds ago Up 14 seconds flamboyant_shirley
    $sudo docker exec -it adc809b50388 /bin/sh
    / #
    / # ls -l /usr/home/
    total 4
    drwxr-xr-x 2 root root 4096 Nov 17 01:13 test
    / # ls -l /usr/home/test/
    total 0
    -rw-r--r-- 1 root root 0 Nov 17 01:13 test.txt
    / # cat /usr/home/test/test.txt
    / #

    上面示例中,首先基于alpine镜像启动了一个容器,通过显示挂载-v /root/test:/usr/home/test将主机的/root/test目录挂载到容器的/usr/home/test目录下,如果镜像中默认没有该目录,则会新建一个这样的目录;docker创建了一个随机名为flamboyant_shirley, ID为adc809b50388的容器。进入容器后查看目录确实已经存在,把容器关闭销毁后文件依然会在主机中。

    当然还可以将具体文件通过显示挂载给容器使用,比如通过指定参数-v:-v /root/test/test.txt:/usr/home/test/test.txt

  2. 使用-v /[container path]进行docker managed volume隐式挂载

    1
    2
    3
    4
    $sudo docker run -it --name myalpine -v /usr/local/lmtest  alpine:x86-3.11.5
    / #
    / # ls /usr/local/lmtest/
    / #

    这里基于alpine镜像启动了一个名为myalpine的容器,隐式挂载并没有指定具体主机目录,容器挂载了一个匿名卷/usr/local/lmtest,初始镜像里并没有这个目录,docker会为其创建一个该目录。使用inspect看看这个匿名卷。

    1
    $sudo docker inspect myalpine

    也可基于容器ID来查看容器情况,会输出很多内容,重点查看存储相关内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    "Mounts": [
    {
    "Type": "volume",
    "Name": "5778513ecf9bf04a44722082c8f5c91ee9f0e30922c17d71529009149c0dcc63",
    "Source": "/var/lib/docker/volumes/5778513ecf9bf04a44722082c8f5c91ee9f0e30922c17d71529009149c0dcc63/_data",
    "Destination": "/usr/local/lmtest",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
    }

    其中Source部分就是Host主机所在目录,Destination部分是容器挂载匿名卷,尝试从Host主机上的挂载目录写一个文件,然后查看容器中的变化。

    • 在主机上添加文件

      1
      2
      3
      [root@ecs_lm_test ~]# cd /var/lib/docker/volumes/5778513ecf9bf04a44722082c8f5c91ee9f0e30922c17d71529009149c0dcc63/_data
      [root@ecs_lm_test _data]# ls
      [root@ecs_lm_test _data]# echo "hello,lm" > test.txt

      在主机共享目录里新增一个test.txt文件,内容为hello,lm

    • 在容器中查看文件

      1
      2
      3
      / # cat /usr/local/lmtest/test.txt
      hello,lm
      / #

      在容器中可见与主机是保持一致的。

    • 销毁容器后查看主机目录

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      [root@ecs_lm_test _data]# docker ps -a
      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
      236406585e9a alpine:x86-3.11.5 "/bin/sh" 16 minutes ago Exited (0) 16 seconds ago myalpine
      [root@ecs_lm_test _data]#
      [root@ecs_lm_test _data]#
      [root@ecs_lm_test _data]# docker rm myalpine
      myalpine
      [root@ecs_lm_test _data]# docker ps -a
      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
      [root@ecs_lm_test_data]# cd /var/lib/docker/volumes/5778513ecf9bf04a44722082c8f5c91ee9f0e30922c17d71529009149c0dcc63/_data
      [root@ecs_lm_test_data]#
      [root@ecs_lm_test_data]#
      [root@ecs_lm_test_data]# ls
      test.txt
      [root@ecs_lm_test_data]#

      可见容器在销毁后文件还是存在于主机目录下。


文章首发公众号:梅旭红,欢迎关注,不定期更新。


全文完。