为了账号安全,请及时绑定邮箱和手机立即绑定

docker容器技术学习笔记(7、docker存储)

标签:
Docker

Docker 存储

Docker 为容器提供了两种存放数据的资源:
1、由 storage driver 管理的镜像层和容器层。
2、Data Volume。

storage driver

Docker 镜像的分层结构,简单回顾一下:

webp

容器由最上面一个可写的容器层,以及若干只读的镜像层组成,容器的数据就存放在这些层中。这样的分层结构最大的特性是 Copy-on-Write:
1、新数据会直接存放在最上面的容器层。
2、修改现有数据会先从镜像层将数据复制到容器层,修改后的数据直接保存在容器层中,镜像层保持不变。
3、如果多个层中有命名相同的文件,用户只能看到最上面那层中的文件。

分层结构使镜像和容器的创建、共享以及分发变得非常高效,而这些都要归功于 Docker storage driver。正是 storage driver 实现了多层数据的堆叠并为用户提供一个单一的合并之后的统一视图

Docker 支持多种 storage driver,有 AUFS、Device Mapper、Btrfs、OverlayFS、VFS 和 ZFS。它们都能实现分层的架构,同时又有各自的特性。对于 Docker 用户来说,具体选择使用哪个 storage driver 是一个难题,因为:
1、没有哪个 driver 能够适应所有的场景。
2、driver 本身在快速发展和迭代。

不过 Docker 官方给出了一个简单的答案:
优先使用 Linux 发行版默认的 storage driver。Docker 安装时会根据当前系统的配置选择默认的 driver。默认 driver 具有最好的稳定性,因为默认 driver 在发行版上经过了严格的测试。

运行docker info可以查看默认 driver。
Ubuntu 用的 AUFS,底层文件系统是 extfs,各层数据存放在 /var/lib/docker/aufs。
Redhat/CentOS 的默认 driver 是 Device Mapper,SUSE 则是 Btrfs。

对于某些容器,直接将数据放在由 storage driver 维护的层中是很好的选择,比如那些无状态的应用。无状态意味着容器没有需要持久化的数据,随时可以从镜像直接创建

Data Volume

有持久化数据的需求,容器启动时需要加载已有的数据,容器销毁时希望保留产生的新数据,也就是说,这类容器是有状态的。这就要用到 Docker 的另一种存储机制:Data Volume。

Data Volume 本质上是 Docker Host 文件系统中的目录或文件,能够直接被 mount 到容器的文件系统中。Data Volume 有以下特点:
1、Data Volume 是目录或文件,而非没有格式化的磁盘(块设备)。
2、容器可以读写 volume 中的数据。
3、volume 数据可以被永久的保存,即使使用它的容器已经销毁。

现在我们有数据层(镜像层和容器层)和 volume 都可以用来存放数据,具体使用的时候要怎样选择呢?考虑下面几个场景:
1、Database 软件 vs Database 数据
2、Web 应用 vs 应用产生的日志
3、数据分析软件 vs input/output 数据
4、Apache Server vs 静态 HTML 文件

相信大家会做出这样的选择:
1、前者放在数据层中。因为这部分内容是无状态的,应该作为镜像的一部分。
2、后者放在 Data Volume 中。这是需要持久化的数据,并且应该与镜像分开存放

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

  • bind mount

bind mount 是将 host 上已存在的目录或文件 mount 到容器。
通过 -v 将其 mount 到容器,-v 的格式为 <host path>:<container path>。
bind mount 时还可以指定数据的读写权限,默认是可读可写,可指定为只读。
除了 bind mount 目录,还可以单独指定一个文件。使用 bind mount 单个文件的场景是:只需要向容器添加文件,不希望覆盖整个目录。

bind mount 的使用直观高效,易于理解,但它也有不足的地方:bind mount 需要指定 host 文件系统的特定路径,这就限制了容器的可移植性,当需要将容器迁移到其他 host,而该 host 没有要 mount 的数据或者数据不在相同的路径时,操作会失败。移植性更好的方式是 docker managed volume。

  • docker managed volume

docker managed volume 与 bind mount 在使用上的最大区别是不需要指定 mount 源,指明 mount point 就行了。

docker managed volume 的创建过程:
1、容器启动时,简单的告诉 docker "我需要一个 volume 存放数据,帮我 mount 到目录 /abc"。
2、docker 在 /var/lib/docker/volumes 中生成一个随机目录作为 mount 源。
3、如果 /abc 已经存在,则将数据复制到 mount 源,
4、将 volume mount 到 /abc
除了通过 docker inspect 查看 volume,我们也可以用 docker volume 命令

两种 data volume 的原理和基本使用方法,下面做个对比:
1、相同点:两者都是 host 文件系统中的某个路径。
2、不同点:

webp

共享数据

  • 容器与 host 共享数据

我们有两种类型的 data volume,它们均可实现在容器与 host 之间共享数据,但方式有所区别。

对于 bind mount 是非常明确的:直接将要共享的目录 mount 到容器。
docker managed volume 就要麻烦点。由于 volume 位于 host 中的目录,是在容器启动时才生成,所以需要将共享数据拷贝到 volume 中。

docker cp 可以在容器和 host 之间拷贝数据,当然我们也可以直接通过 Linux 的 cp 命令复制到 /var/lib/docker/volumes/xxx。

  • 容器之间共享数据

1、用bind mount共享数据
第一种方法是将共享数据放在 bind mount 中,然后将其 mount 到多个容器。

2、用volume container共享数据
另一种在容器之间共享数据的方式是使用 volume container。volume container 是专门为其他容器提供 volume 的容器。它提供的卷可以是 bind mount,也可以是 docker managed volume。

下面我们创建一个 volume container:

docker create --name vc_data -v ~/htdocs:/usr/local/apache2/htdocs -v /other/useful/tools busybox

我们将容器命名为 vc_data(vc 是 volume container 的缩写)。注意这里执行的是 docker create 命令,这是因为 volume container 的作用只是提供数据,它本身不需要处于运行状态。容器 mount 了两个 volume:

1、bind mount,存放 web server 的静态文件。
2、docker managed volume,存放一些实用工具(当然现在是空的,这里只是做个示例)。
通过 docker inspect 可以查看到这两个 volume

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

docker run --name web1 -d -p 80 --volumes-from vc_data httpd

容器已经成功共享了 volume container 中的 volume。

下面我们讨论一下 volume container 的特点:
1、与 bind mount 相比,不必为每一个容器指定 host path,所有 path 都在 volume container 中定义好了,容器只需与 volume container 关联,实现了容器与 host 的解耦。
2、使用 volume container 的容器其 mount point 是一致的,有利于配置的规范和标准化,但也带来一定的局限,使用时需要综合考虑。

3、用data-packed volume container共享数据
volume container 的数据归根到底还是在 host 里,有没有办法将数据完全放到 volume container 中,同时又能与其他容器共享呢?

当然可以,通常我们称这种容器为 data-packed volume container。其原理是将数据打包到镜像中,然后通过 docker managed volume 共享。

volume 生命周期管理

Data Volume 中存放的是重要的应用数据,如何管理 volume 对应用至关重要。

  • 备份

因为 volume 实际上是 host 文件系统中的目录和文件,所以 volume 的备份实际上是对文件系统的备份。

  • 恢复

volume 的恢复也很简单,如果数据损坏了,直接用之前备份的数据拷贝到 /myregistry 就可以了。

  • 迁移

如果我们想使用更新版本的 Registry,这就涉及到数据迁移,方法是:
1、docker stop 当前 Registry 容器。
2、启动新版本容器并 mount 原有 volume。
docker run -d -p 5000:5000 -v /myregistry:/var/lib/registry registry:latest

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

  • 销毁

docker 不会销毁 bind mount,删除数据的工作只能由 host 负责。对于 docker managed volume,在执行 docker rm 删除容器时可以带上 -v 参数,docker 会将容器使用到的 volume 一并删除,但前提是没有其他容器 mount 该 volume,目的是保护数据,非常合理。

删除容器时没有带 -v 呢?这样就会产生孤儿 volume,可以用 docker volume rm 删除。如果想批量删除孤儿 volume,可以执行:
docker volume rm $(docker volume ls -q)



作者:阳一yayi
链接:https://www.jianshu.com/p/5440da2c9ef7


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消