Docker存储之storage driver和Data Volume

13 篇文章 1 订阅
13 篇文章 0 订阅

Docker存储之Storage Driver和Data Volume

在使用 Docker 的过程中,势必需要查看容器内应用产生的数据,或

者需要将容器内数据进行备份,甚至多个容器之间进行数据共享,这就必然

会涉及到容器的数据管理

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

A、由 Storage Driver 管理的镜像层和容器层

B、Data Volume

 

一、Storage Driver

容器 = 1个最上层的可写容器层 + N干只读镜像层组成

容器的数据 就存放在这些层中

分层结构的特性是 Copy-on-Write:

A、新数据 直接存放在最上层的容器层

B、修改现有数据 先从镜像层将数据复制到容器层修改后的数据 直接保存在容器层,镜像层保持不变

C、如果N个层中有命名相同的文件,用户只能看到最上面那层中的文件

 

Docker Storage Driver 实现了多层数据的堆叠并为用户提供一个单一的合并之后的统一视图

Docker 支持多种 Storage Driver,有 AUFS、Device Mapper、Btrfs、OverlayFS、VFS 和 ZFS 它们都能实现分层的架构,同时又有各自的特性

 

Docker 官方给出:

优先使用 Linux 发行版默认的 Storage Driver

Docker 安装时会根据当前系统的配置选择默认的 driver

默认 driver 具有最好的稳定性,因为默认 driver 在发行版上经过了严格的测试

 

查看本机Docker使用的Storage Driver:

docker info

Client:

 Debug Mode: false

Server:

 Containers: 3

  Running: 3

  Paused: 0

  Stopped: 0

 Images: 13

 Server Version: 19.03.8

 Storage Driver: overlay2

  Backing Filesystem: <unknown>

  Supports d_type: true

  Native Overlay Diff: true

 Logging Driver: json-file

 Cgroup Driver: cgroupfs

 Plugins:

  Volume: local

  Network: bridge host ipvlan macvlan null overlay

  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog

 Swarm: inactive

 Runtimes: runc

 Default Runtime: runc

 Init Binary: docker-init

 containerd version: 7ad184331fa3e55e52b890ea95e65ba581ae3429

 runc version: dc9208a3303feef5b3839f4323d9beb36df0a9dd

 init version: fec3683

 Security Options:

  seccomp

   Profile: default

 Kernel Version: 3.10.0-862.el7.x86_64

 Operating System: CentOS Linux 7 (Core)

这里CentOS 7 使用:Storage Driver: overlay2

1、无状态容器

直接将数据放在由 Storage Driver 维护的层中是很好的选择,

无状态意味着容器没有需要持久化的数据,随时可从镜像直接创建

例如: busybox,是一个工具箱,启动 busybox 是为执行诸如 wget,ping 之类命令,不需要保存数据供以后使用,使用完直接退出,容器删除时存放在容器层中的工作数据也一起被删除,下次再启动新容器即可

2、有状态容器

有持久化数据的需求,容器启动时需要加载已有的数据,容器销毁时希望保留产生的新数据

这时需要使用,Docker 另一种存储机制:Data Volume

 

二、Data Volume

Data Volume 是 Docker Host 文件系统中的目录或文件,能够直接被 mount 到容器的文件系统中

 

Data Volume 有以下特点:

A、Data Volume 是目录或文件,不是没有格式化的磁盘(块设备)

B、容器可读写 volume 中的数据

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

 

数据层(镜像层和容器层)和 volume 都可以用来存放数据,应如何选择?

A、Database 软件  vs   Database 数据

B、Web 应用       vs   应用产生的日志

C、数据分析软件   vs   input/output 数据

D、Apache Server  vs   静态 HTML 文件

前者放在数据层,因为这部分内容是无状态的,应该作为镜像的一部分

后者放在 Data Volume ,这是需要持久化的数据,并且应该与镜像分开存放

 

如何设置 voluem 的容量?

volume 是 docker host 文件系统的一部分,所以 volume 的容量取决于host文件系统当前未使用的空间,目前还没有方法设置 volume 的容量

docker 从使用方式角度,提供2种类型的 volume:

bind mount 和 docker managed volume

 

1、bind mount

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

 

情景1:

docker host 上有目录 $HOME/htdocs:

cat  htdocs/index.html

this is a file in host file system  !haha

-v  参数 ,mount 到 httpd容器:

docker  run  -d  -p  80:80 --name=web02 -v  ~/htdocs:/usr/local/apache2/htdocs  httpd

指令解析:

-v 的格式为 <host path>:<container path>

/usr/local/apache2/htdocs 是 apache server 存放静态文件的地方

由于 /usr/local/apache2/htdocs 已经存在,原有数据会被隐藏起来,取而代之的是 host $HOME/htdocs/ 中的数据,这与 Linux mount 命令的行为是一致的

从host上访问httpd容器:

curl  127.0.0.1:80

结果显示:当前主页确实是 $HOME/htdocs/index.html 中的内容

更新一下,看是否能生效:

echo “update  2020-05-27”  >>  ~/htdocs/index.html

再从host上访问httpd容器

curl  127.0.0.1:80

事实证明:

host 中的修改确实生效了,bind mount 可让 host 与容器共享数据

 

情景2:

当httpd的web02容器销毁

docker  stop  web02

docker  rm    web02

cat  ~/htdocs/index.html

事实证明:

即使容器被删除,bind mount 也还在,因为bind mount是host里面的文件

 

情景3:

bind mount 指定数据的读写权限,默认是可读可写rw,可指定为只读ro

docker  run  -d  -p  80:80  -v  ~/htdocs:/usr/local/apache2/htdocs:ro  httpd

docker  exec  -it  web02  bash

echo  "add  data"  >>  htdocs/index.html

指令解析:

ro 设置了只读权限,在容器中是无法对 bind mount 数据进行修改的

只有 host 有权修改数据,提高了安全性

 

情景4:

bind mount 除了目录,还可单独指定一个文件

docker  run  -d  -p  80:80 --name=web02 -v  ~/htdocs/index.html:/usr/local/apache2/htdocs/new-index.html  httpd

从host上访问httpd容器默认文件:

curl  127.0.0.1:80

从host上访问httpd容器bind mount上去的文件:

curl  127.0.0.1:80/new-index.html

将 html 文件加到 apache 中,同时保留容器原有的数据

应用场景:

bind mount 单个文件,只需向容器添加文件,不覆盖整个目录

注意事项:

host 中的源文件必须存在,否则会当作一个新目录 bind mount 给容器

mount point 应用场景:

A、将源代码目录 mount 到容器中,在 host 中修改代码就能看到应用的实时效果

B、将 mysql 容器的数据放在 bind mount 里,这样 host 可以方便地备份和迁移数据

bind mount 不足之处:

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

 

2、Docker Managed Volume

针对容器,移植性更好的方式是 docker managed volume

docker managed volume 是不需要指定 mount 源,指明 mount point 即可

案例说明:

docker  run  -d  -p  80:80  -v  /usr/local/apache2/htdocs  httpd

指令解析:

-v  参数,通知docker需要1个data volume ,并把它mount到 /usr/local/apache2/htdocs

data volume 具体位置:

docker  ps -a

docker  inspect c03f4ae8f062  | grep -A 10  Mounts

Mounts 内容,显示容器当前使用的所有 data volume,包括 bind mount 和 docker managed volume

Source 就是该 volume 在 host 上的目录

动作解析:

当容器申请 mount docker manged volume 时,docker 都会在/var/lib/docker/volumes 下生成一个目录(此处是

/var/lib/docker/volumes/19bb48d5ee0b3d3d04d3953044587c562873b19a3ce79e0395b083429a0e20c3/_data),该目录就是 mount 源

分析Volumes:

ls  -l /var/lib/docker/volumes/19bb48d5ee0b3d3d04d3953044587c562873b19a3ce79e0395b083429a0e20c3/_data

cat /var/lib/docker/volumes/19bb48d5ee0b3d3d04d3953044587c562873b19a3ce79e0395b083429a0e20c3/_data/index.html

curl 127.0.0.1:80

volume 的内容跟容器原有 /usr/local/apache2/htdocs 完全一样

因为 mount point 指向的是已有目录,原有数据会被复制到 volume 中

/usr/local/apache2/htdocs 已不再是由 storage driver 管理的层数据了,它已是一个 data volume

对数据进行更改:

echo  add data  >>

/var/lib/docker/volumes/19bb48d5ee0b3d3d04d3953044587c562873b19a3ce79e0395b083429a0e20c3/_data/index.html

curl 127.0.0.1:80

docker managed volume 创建过程:

A、容器启动时,告诉 docker "我需要一个 volume 存放数据,帮我 mount 到目录 /abc"

B、docker 在 /var/lib/docker/volumes 中生成一个随机目录作为 mount 源

ll  /var/lib/docker/volumes

C、若 /abc 已存在,则将数据复制到 mount 源

D、将 volume mount 到 /abc

 

查看volume 命令:

docker  inspect c03f4ae8f062  | grep -A 10  Mounts

docker volume   ls

docker volume   inspect  VOLUME NAME

docker volume 的局限性:

只能查看 docker managed volume

看不到 bind mount

无法知道 volume 对应的容器

bind mount 与 docker managed volume 的区别

两种 data volume 实际上都是使用 host 文件系统的中的某个路径作为 mount 源

不同之处在于:

 不同点

bind mount

docker managed volume

 volume 位置

可任意指定

/var/lib/docker/volumes/...

 对已有mount point 影响

隐藏并替换为 volume

原有数据复制到 volume

 是否支持单个文件

支持

不支持,只能是目录

 权限控制

可设置为只读,默认为读写权限

无控制,均为读写权限

 移植性

移植性弱,与 host path 绑定

移植性强,无需指定 host 目录

 

 

 

三、volume 关键特性--数据共享

1、容器与 host 共享数据

两种类型的 data volume,可在容器与 host 之间共享数据

A、bind mount 方式:

直接将要共享的目录 mount 到容器

B、docker managed volume 方式:

volume 位于 host 中的目录,是容器启动时生成的,需将共享数据拷到 volume 中

(1)  容器和 host 之间拷贝数据

docker  cp  ~/htdocs/index.html  c03f4ae8f062:/usr/local/apache2/htdocs

curl  127.0.0.1:80

(2)  Linux 的 cp 命令复制

ll  /var/lib/docker/volumes/xxx

2、容器之间共享数据

方法1:

将共享数据放在 bind mount 中,然后将其 mount 到多个容器

实例演示:

3个 httpd 容器组成的 web server 集群,使用相同的 html 文件

A、将 $HOME/htdocs mount 到三个 httpd 容器

docker  run  --name web0  -d  -p 8080:80  -v ~/htdocs:/usr/local/apache2/htdocs  httpd

docker  run  --name web1  -d  -p 8081:80  -v ~/htdocs:/usr/local/apache2/htdocs  httpd

docker  run  --name web2  -d  -p 8082:80  -v ~/htdocs:/usr/local/apache2/htdocs  httpd

B、查看当前web0、web1、web2 三容器的主页

docker  ps

curl  127.0.0.1:8080

curl  127.0.0.1:8081

curl  127.0.0.1:8082

C、修改 volume 中主页内容,核实web容器集群主页的更新情况

pwd

cat htdocs/index.html

echo  20200528 add test to web  container Cluster  >>  htdocs/index.html

cat htdocs/index.html

curl  127.0.0.1:8080

curl  127.0.0.1:8081

curl  127.0.0.1:8082

 

方法2:

使用 volume container

volume container 是专门为其他容器提供 volume 的容器。它提供的卷可以是 bind mount,也可以是 docker managed volume

实例演示:

创建1个volume container

docker  create  --name=vc-data \

        -v  ~/htdocs:/usr/local/apache2/htdocs \

-v  /other/useful/tools \

busybox

指令解析:

--name=  vc-data 容器名称

docker  create 命令,volume container 是提供数据,自身不需要处于运行状态

-v 参数,容器mount了2个volume

bind mount 存放web 静态文件

docker managed volume 存放实用工具(此处为空)

docker  inspect  vc-data  |  grep -A 20 Mounts

 

使用volume container:

--volumes-from 参数,使用 名为 vc-data 的 volume container

docker  run  --name web3  -d  -p 8083:80  --volumes-from  vc-data  httpd

docker  run  --name web4  -d  -p 8084:80  --volumes-from  vc-data  httpd

docker  run  --name web5  -d  -p 8085:80  --volumes-from  vc-data  httpd

docker  ps

查看 httpd 容器对应的 volume

docker  inspect  web3  |  grep -A 20 Mounts

A、httpd 容器都用 vc-data 的 volume

B、mount point 都一样

C、数据共享

修改前

cat htdocs/index.html

curl  127.0.0.1:8083

curl  127.0.0.1:8084

curl  127.0.0.1:8085

做修改

pwd

cat htdocs/index.html

echo  add volume container  >>  htdocs/index.html

cat htdocs/index.html

修改后

curl  127.0.0.1:8083

curl  127.0.0.1:8084

curl  127.0.0.1:8085

得出结论:

web3、web4、web5 容器共享 名为 vc-data 的 volume container 中的 volume

volume container 的特点:

A、与 bind mount 相比,无需为每一个容器指定 host path,所有 path 都在 volume container 中定义好了,容器只需与 volume container 关联,容器与 host 是解耦的

B、使用 volume container 的容器其 mount point 是一致的,有利于配置的规范和标准化,同时也带来一定的局限,使用时需要综合考虑

C、volume container 的数据归根到底还是在 host 里

 

方法3:

使用data-packed volume container

将数据完全放到 volume container 中,同时又能与其他容器共享

容器 data-packed volume container 原理:

将数据打包到镜像中,然后通过 docker managed volume 共享

实例演示:

A、编辑Dockfile 构建镜像

# This my first busybox Dockerfile

# Version 1.0

# data-packed volume container

FROM busybox

#MAINTAINER

MAINTAINER zola

#ENV

#ADD

ADD  htdocs  /usr/local/apache2/htdocs

VOLUME  /usr/local/apache2/htdocs

#RUN

#WORKDIR

#EXPOSE

#CMD

文件解析:

ADD 将静态文件添加到容器目录 /usr/local/apache2/htdocs

VOLUME 的作用与 -v 等效,用来创建 docker managed volume,mount point 为 /usr/local/apache2/htdocs,因为这个目录就是 ADD 添加的目录,所以会将已有数据拷贝到 volume 中

B、build 新镜像 datapacked

docker  build  -t  datapacked  .

列出各个层(layer)的创建信息:

docker history  datapacked

查看详情:

docker history --no-trunc datapacked

C、用新镜像 datapacked 创建 data-packed volume container

docker  create  --name  vc_data  datapacked

指令解析:

因 Dockerfile 中已经使用了 VOLUME 指令,这里不需要再指定 volume 的 mount point

D、启动 httpd 容器并使用 data-packed volume container

docker  run  -d --name=web6 -p  8086:80  --volumes-from  vc_data  httpd

curl  127.0.0.1:8086

验证结果:

web6 容器能够正确读取 volume 中的数据

应用场景:

data-packed volume container 是自包含的,不依赖 host 提供数据,具有很强的移植性,非常适合 只使用 静态数据的场景,比如应用的配置信息、web server 的静态文件等

 

四、管理volume的生命周期

如何备份、恢复、迁移和销毁 volume

1、备份

volume 是 host 文件系统中的目录和文件

volume 的备份实际上是对文件系统的备份

搭建本地 Registry:

docker  run  -d  -p  5000:5000  -v  /myregistry:/var/lib/registry   registry:2

所有的本地镜像都存在 host 的 /myregistry 目录中,我们要做的就是定期备份这个目录。

ll  /myregistry

2、恢复

volume 的恢复简单,若数据损坏,直接用备份的数据拷贝到 /myregistry 即可

3、迁移

若想新 Registry 版本,需要数据迁移

A、docker stop 当前 Registry 容器

B、启动新版本容器并 mount 原有 volume

docker run -d -p 5000:5000 -v /myregistry:/var/lib/registry registry:latest

C、在启用新容器前要确保新版本的默认数据路径是否发生变化

4、销毁

删除不再需要的 volume,volume 删除后数据找不回来

A、bind mount

docker 不会销毁 bind mount,删除数据的工作只能由 host 负责

B、docker managed volume

前提条件:没有其他容器 mount 该 volume,目的是保护数据

在执行 docker rm 删除容器时可带上 -v 参数,docker 会将容器使用到的 volume 一并删除

遗留问题:

删除容器时没有带 -v ,会产生孤儿 volume

docker 提供了 volume 子命令可以对 docker managed volume 进行维护

docker  volume  ls

docker  run  --name  bubox  -v  /test/data  busybox

查看docker managed volume:

docker  volume  ls

删除容器:

docker  rm  bubox

docker  volume  ls

删除孤儿 volume:

docker volume rm c793ada1bf22b0bee6000f435994e49af3ecfd73a93b52f0b24091e851fb5650

docker  volume  ls

批量删除孤儿volume:

docker  volume  rm$(docker  volume  ls  -q)

 

五、总结概述

1、Docker 为容器提供了两种存储资源:  数据层和 Data Volume

2、数据层包括:  镜像层和容器层,由 storage driver 管理

3、Data Volume 分2种类型:  bind mount 和 docker managed volume

4、bind mount 作用:  容器与 host 之间,容器与容器之间共享数据

5、volume container 是具有更好移植性的容器间数据共享方案,特别是 data-packed volume container

6、Data Volume的管理:  备份、恢复、迁移和销毁

详情请见,微信公众号

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值