Docker存储

Docker存储

Docker为容器提供了两种存放数据的资源

      1. storage driver管理的镜像层和容器层

      2. Date Volume

storage driver

      容器由最上面一个可写的容器层和若干只读的镜像层组成,容器的数据就存在这些层中。这种分层结构最大的特点是Copy-on-Write

            1. 新数据会直接存放在最上面的容器层

            2. 修改现有数据会先从镜像层复制文件到容器中,再在容器层修改并保持,镜像层的数据不会发生改变

            3. 若多个层中有命名相同的文件,用户只能看到最上面一层的文件

Date volume之bind mount

Date volume的特点

      1. Date volume是目录或文件,而非没有格式化的磁盘

      2. 容器可以读写volume中的数据

      3. volume数据可以被永久保存,即使使用它的容器已经销毁

docker提供两种类型的volume:bind mount和docker managed volume

      bind mount是将host上已经存在的目录或文件mount容器

      例如docker host上有目录$HOME/test

      通过-v将其mount到httpd容器 

      -v的格式为<host path>:<container path>。/usr/local/apache2/test就是apache server存放静态文件的地方。由于/usr/local/apache2/test已经存在,原有数据会被隐藏起来,取而代之的是host $HOME/test/ 中的数据,这与linux mount命令的行为是一致的。

      下面我们进入到容器里面去查看mount过去的目录及其文件 

      这与host下的文件内容一致,现在我们在host中对文件内容进行更新,再进入容器查看修改后的文件,由结果可以看出,在host中修改了index.html文件的内容,容器中文件的内容也跟着被修改 

      也可以使用参数来修改文件的权限,比如下面的例子使用ro将文件设置为只读,容器不能对该文件进行修改,只有在host里面才有权限修改文件

      使用bind mount单个文件的场景是:只需要向容器添加文件,不希望覆盖整个目录。在上面的例子中,我们将html文件加到apache中,同时也保留了容器原有的数据。

      使用单一文件有一点要注意:host中的源文件必须要存在,不然会当作一个新目录bind mount给容器。

      mount point有很多应用场景,比如我们可以将源代码目录mount到容器中,在host中修改代码就能看到应用的实时效果。再比如将mysql容器的数据放在bind mount里,这样host可以方便地备份和迁移数据。

      bind mount不足的地方:bind mount需要指定host文件系统的特定路径,这就限制了容器的可移植性,当需要将容器迁移到其他host,而该host没有要mount的数据或者数据不在相同的路径时,操作会失败。

docker managed volume

      docker managed volume与bind mount最大的区别是不需要指定mount源,指明mount point就行了,还是以httpd容器为例,创建容器后并用inspect来查看mount源

      docker manages volume的创建过程

            1. 容器启动时,简单告诉docker“我需要一个volume存放数据,帮我mount到目录/abc”

            2. docker在 /var/lib/docker/volume中生成一个随机目录作为mount源

            3. 如果/abc已存在,则将数据复制到mount源

            4. 将volume mount到/abc

容器与host共享数据

      有两种类型的data volume,它们都可以实现在容器与host间共享数据

      对于bind mount:直接将要共享的目录mount到容器,可以参照前面的例子

      docker managed volume要麻烦些。由于volume位于host中的目录,是在容器启动时才生成,所以需要将共享数据copy到volume中,可以用docker cp在容器与host之间进行文件拷贝 

容器之间共享数据

      第一种实现方法是将共享数据放在bind mount中,然后再mount到多个容器。先创建三个httpd容器组成web server集群,它们使用相同的html文件,具体操作如下

      1. 将HOME/test mount到三个httpd容器

      2. 查看当前主页内容 

      3. 修改volume中的主页文件,再次查看并确认所有容器文件都使用了新的主页

      另一种方法是用volume container共享数据,下面创建一个volume container

      这里执行的是docker create命令,因为volume container的作用只是提供数据,它本身不需要处于运行状态。容器mount了两个volume

            1. bind mount,存放web server静态文件

            2. docker managed volume,存放一些实用工具(这里为空,只是为了演示)

      通过docker inspect vc_date来查看这两个volume 

      其他容器可以通过--volumes-from使用vc_date这个volume container 

      三个容器都使用了vc_date,以web4为例查看它的volume 

      web4容器使用的是vc_date的volume,而且mount point都是一样的,验证一下数据共享结果,由结果可以看出三个容器已经成功共享了volume container的volume 

data-packed volume container

      可以将数据完全放在volume container中,与其他容器共享。其方法是将数据打包到镜像,然后通过docker managed volume共享

      用Dockerfile构建镜像,其中ADD将静态文件添加到容器目录,VOLUME的作用于-v等效,用来创建docker manage volume

      build新镜像datapacked 

      用新镜像创建data-packed volume container 

      因为在Dockerfile中使用了VOLUME指令,这里就不需要指定volume的mount point了。启动httpd容器并使用data-packed volume container 

      容器能够正确读取volume中的数据,data-packed volume container是自包含的,不依赖于host提供数据,具有很强的移植性,非常适合只用静态数据的场景,比如web server静态文件

volume生命周期管理

备份

      前面搭建了一个本地Registry,并可以通过本地搭建的Registry来运行容器。所有的本地镜像都存在host的 /myregistry目录下,我们要定期备份这个目录 

恢复

      volume的恢复很简单,如果数据损坏了,直接用之前备份的数据copy到/myregistry下即可

迁移

      1. docker stop当前Registry容器

      2. 启动新版本容器并mount原有volume

docker run -d -p 5000:5000 -v /myregistry:/usr/lib/registry registry:lastest

销毁

      docker不会销毁bind mount,删除数据只能在host上执行。对于docker managed volume,在执行docker rm时可以带上-v参数,docker会将容器使用到的volume一并删除,但前提是没有其他容器mount该volume。也可以用docker volume ls来查看当前的volume,docker volume rm来删除遗留下来的volume。如果想要批量删除遗留的volume,可以使用以下命令

docker volume rm $(docker volume ls -q)
原文地址:https://www.cnblogs.com/chenjin2018/p/9840649.html