Docker 为容器提供了两种存放数据的资源:
1、由 storage driver 管理的镜像层和容器层。
2、Data Volume。
storage driver
在前面镜像章节我们学习到 Docker 镜像的分层结构。
容器由最上面一个可写的容器层,以及若干只读的镜像层组成,容器的数据就存放在这些层中。这样的分层结构最大的特性是 Copy-on-Write:
1、新数据会直接存放在最上面的容器层。
2、修改现有数据会先从镜像层将数据复制到容器层,修改后的数据直接保存在容器层中,镜像层保持不变。
3、如果多个层中有命名相同的文件,用户只能看到最上面那层中的文件。
分层结构使镜像和容器的创建、共享以及分发变得非常高效,而这些都要归功于 Docker storage driver。正是 storage driver 实现了多层数据的堆叠并为用户提供一个单一的合并之后的统一视图。
Docker 支持多种 storage driver,有 AUFS、Device Mapper、Btrfs、OverlayFS、VFS 和 ZFS。它们都能实现分层的架构,同时又有各自的特性。
优先使用 Linux 发行版默认的 storage driver。
Docker 安装时会根据当前系统的配置选择默认的 driver。默认 driver 具有最好的稳定性
运行docker info
查看 Ubuntu 的默认 driver:
运行docker info
查看 Linux 的默认 driver:
Red Hat Enterprise Linux:4.x版本内核或更高版本 + Docker 17.06 版本或更高版本,建议使用 Overlay2。
Red Hat Enterprise Linux:低版本内核或低版本的 Docker,建议使用 Device Mapper。
Ubuntu Linux:4.x 版本内核或更高版本,建议使用 Overlay2。
Ubuntu Linux:更早的版本建议使用 AUFS。
SUSE Linux Enterprise Server:Btrfs
Linux要使用 device mapper,可以通过--storage-driver daemon 选项或通过在 daemon.json 配置文件中设置 “storage-driver” 来手动配置要使用的存储驱动
Data Volume 之 bind mount
Data Volume 本质上是 Docker Host 文件系统中的目录或文件,能够直接被 mount 到容器的文件系统中。Data Volume 有以下特点:
1、Data Volume 是目录或文件,而非没有格式化的磁盘(块设备)。
2、容器可以读写 volume 中的数据。
3、volume 数据可以被永久的保存,即使使用它的容器已经销毁。
考虑下面几个场景:
1、Database 软件 vs Database 数据
2、Web 应用 vs 应用产生的日志
3、数据分析软件 vs input/output 数据
4、Apache Server vs 静态 HTML 文件
相信大家会做出这样的选择:
1、前者放在数据层中。因为这部分内容是无状态的,应该作为镜像的一部分。
2、后者放在 Data Volume 中。这是需要持久化的数据,并且应该与镜像分开存放。
bind mount
bind mount 是将 host 上已存在的目录或文件 mount 到容器。
例如 docker host 上有目录 $HOME/htdocs:
通过 -v
将其 mount 到 httpd 容器:
docker run -d -p 80:80 -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
命令的行为是一致的
curl 显示当前主页确实是 $HOME/htdocs/index.html 中的内容。更新一下,看是否能生效:
host 中的修改确实生效了,bind mount 可以让 host 与容器共享数据
容器没有了,bind mount 也还在
bind mount 时还可以指定数据的读写权限,默认是可读可写,可指定为只读:
ro
设置了只读权限,在容器中是无法对 bind mount 数据进行修改的。只有 host 有权修改数据,提高了安全性。
除了 bind mount 目录,还可以单独指定一个文件:(使用 bind mount 单个文件的场景是:只需要向容器添加文件,不希望覆盖整个目录,再比如将 mysql 容器的数据放在 bind mount 里,这样 host 可以方便地备份和迁移数据)
bind mount 需要指定 host 文件系统的特定路径,这就限制了容器的可移植性,当需要将容器迁移到其他 host,而该 host 没有要 mount 的数据或者数据不在相同的路径时,操作会失败
docker managed volume
与 bind mount 在最大区别是不需要指定 mount 源,指明 mount point 就行了
通过 -v 告诉 docker 需要一个 data volume
docker inspect 的输出中 Mounts 的部分,显示容器当前使用的所有 data volume,包括 bind mount 和 docker managed volume。
使用 docker inspect 391332c77cdf 查看下 Mounts 的信息
Source 就是该 volume 在 host 上的目录
每当容器申请 mount docker manged volume 时,docker 都会在/var/lib/docker/volumes 下生成一个目录,这个目录就是 mount 源,这个目录下都有这些文件:
volume 的内容跟容器原有 /usr/local/apache2/htdocs 完全一样的,是因为mount point 指向的是已有目录,原有数据会被复制到 volume 中。
此时的 /usr/local/apache2/htdocs 已经不再是由 storage driver 管理的层数据了,它已经是一个 data volume。我们可以像 bind mount 一样对数据进行操作,例如更新数据
除了通过 docker inspect 查看 volume,我们也可以用 docker volume 命令:
缺点:
docker volume 只能查看 docker managed volume,还看不到 bind mount;同时也无法知道 volume 对应的容器,这些信息还得靠docker inspect。
两种 data volume 的原理和基本使用方法的对比:
相同点:
两者都是 host 文件系统中的某个路径。
不同点:
来源:CSDN
作者:junior1206
链接:https://blog.csdn.net/cojn52/article/details/104664320