Docker 为容器提供了两种存放数据的资源:
容器由最上面一个可写的容器层 + 若干只读的镜像层组成,容器的数据就存放在这些层中。
这样分层的特性就是 Copy-on-Write:
分层结构使镜像和容器的创建、共享以及分发变得非常高效,而这些都要归功于 Docker storage driver。storage driver实现了多层数据的堆叠并为用户提供一个单一的合并之后的统一视图。
Docker 支持多种storage driver,有 AUFS、Device Mapper、Btrfs、OverlayFS、VFS 和 ZFS。它们都能实现分层的架构,同时又有各自的特性。Docker官方推荐优先使用 Linux 发行版默认的 storage driver.
Docker 安装时会根据当前系统的配置选择默认的 driver。默认driver 经过了严格的测试,具有最好的稳定性。
使用 docker info
命令可以查看默认的 driver:
Ubuntu 默认 driver用的是 AUFS,底层文件系统是 exts,各层数据存放在 /var/lib/docker/aufs。
❝对于那些无状态的应用容器,直接将数据放在由 storage driver 维护的层中是很好的选择,无状态意味着容器没有需要持久化的数据,随时可以从镜像直接创建,不需要保存数据供以后使用,使用完直接退出,容器删除时存放在容器层中的工作数据也一起被删除。 ❞
对于有状态的容器,有持久化数据的需求,容器在启动时需要加载已有的数据,销毁的时候需要保留产生的新数据,就需要使用 「Data Volume」 存储机制。
Data Volume 是Docker Host 文件系统中的目录或文件,能够直接被 mount 到容器的文件系统中。
Data Volume 的特点:
volume 是docker host 文件系统的一部分,所以 volume 的容量取决于文件系统当前未使用的空间,在具体的使用上,docker 提供了两种类型的 volume: bind mount 和 docker managed volume。
bind mount 是将 host 上存在的目录或文件 mount 到容器。
运行容器时,使用 -v
来 mount 到容器上。
-v
的格式:<host path>:<container path>
例如,将 ~/data 挂载到 httpd 容器上,如下:
由于 /usr/local/apache2/htdocs 已经存在,原有的数据会被隐藏起来,使用的是挂载的 host 上的 ~/data/ 中的数据。我们修改 host 上的内容,再次查看,发现 bind mount 可以让 host 与容器共享数据,如下:
将容器销毁,可以看到 bind mount 也还存在,「bind mount 不会随着容器的销毁而删除」,如下:
bind mount 还可以指定数据的读写权限,默认是可读可写,可以指定为只读:
docker run -d -p 8080:80 -v ~/data:/usr/local/apache2/htdocs:ro httpd
ro
:设置了只读权限,在容器中便无法对 bind mount 数据进行修改。❝bind mount 不足的地方:bind mount 需要指定 host 文件系统的特定路径,这就限制了容器的可移植性,当需要将容器迁移到其他 host, 而该 host 没有要 mount 的数据或者数据不在相同的路径时,操作会失败。 移植性更好的方式是使用 docker managed volume。 ❞
docker managed volume 不需要指定 mount 源,指明 mount point 就可以了,同样使用 -v ,告诉 docker 需要一个 data volume,并 mount 到 /usr/local/apache2/htdocs :
docker run -d -p 8080:80 -v /usr/local/apache2/htdocs httpd
data volume 具体在哪?我们可以执行 docker inspect
命令在容器的配置信息中找到,如下(其他信息已省略):
其中 Mounts 这部分会显示容器当前使用的所有 data volume,包括 bind mount 和 docker managed volume。
❝「Source 就是该 volume 在 host 上的目录」 当容器申 请 mount docker manged volume 时,docker 都会在var/lib/docker/volumes 下生成一个目录(如:/var/lib/docker/volumes/b3ed2d6d09750f5b8ef4ea613ba38f2511ba1c122ff3db339a061c0ed0d6d41d/_data),这个日录就是 mount 源。 同时,如果 mount point 指向的是已有的目录(如上/usr/local/apache2/htdocs),原有的数据会被复制到 volume 中,所以我们 host 上生成的目录中的内容,会和 /usr/local/apache2/htdocs 中完全一致。 ❞
docker managed volume 创建过程:
例如前面的 httpd 例子,可直接将需要共享的目录 mount 到容器。
这种类型的 data volume 是在容器启动的时候才生成的,所以需要将共享的数据复制到 volume 中,如:
上面我们使用的是 docker cp ,我们还可以直接通过 linux 的 cp 命令复制到 /var/lib/docker/volumes/...
中。
将共享数据放在 bind mount 中,然后将其 mount 到多个容器。
volume container 是专门为了给其他容器提供 volume 的容器,它提供的卷可以是 bind mount,也可以是 docker managed volume。
我们创建(docker create ...)一个名为 vc_data 的容器,vc 是 volume container 的缩写。创建容器,但不运行,因为 此容器只是提供数据,并不需要运行,如下:
容器 mount 两个 volume:
docker inspect 看下俩 volume:
其他容器通过 --volumes-from 来使用 vc_data 这个 volume container :
以 httpd1 为例,看下 volume:
数据共享效果:
上面的 volume container 的数据其实还是在 host 里,而 data-packed volume container 是将数据打包到镜像中,再通过 docker managed volume 共享。
通过如下 Dockerfile 构建镜像 datapacked :
❝ADD 将静态文件添加到容器目录 usr/local/apache2/htdocs. VOLUME 的作用与 -v 等效,用来创建 docker managed volume,mount point为 usr/local/apache2/htdocs,因为这个目录就是 ADD 添加的目录,所以会将已有数据复制到volume中。 ❞
用新镜像创建 data-packed volume container:
Dockerfile 中我们使用了 VOLUME 指令,这里就不需要指定 volume 的mount point 了。启动 httpd 容器并使用 data-packed volume container:
❝容器能够正确读取volume中的数据。data-packed volume container 是自包含的,不依赖 host,具有很强的移植性,非常适合只使用静态数据的场景,比如应用的配置信息、Web server的静态文件等。 ❞
Data Volume 中存放的是重要的应用数据,我们应该重视对 volume 的备份、恢复、销毁等操作。
volume 其实就是 host 文件系统中的资源,备份的话实际上就是对文件系统的备份。
volume 的恢复,只需要将之前备份数据复制到 volume 中即可。
需要注意的是,volume 删除后数据便找不回来了。
docker 不会销毁 bind mount,删除数据的工作只能由 host负责。
在执行docker rm 删除容器时使用 -v
参数,docker会将容器使用到的 volume 一起删除,「前提是该 volume 没有其他容器使用」,这样可以做到对数据的保护。
如果没有使用 -v
参数,那么就会产生孤儿 volume,后期我们可以使用 docker volume
命令对其维护。
❝删除一个或多个卷。无法删除容器正在使用的卷。 ❞
docker info
命令:查看系统默认的 driverdocker volume
命令:管理卷docker inspect
命令:查看容器的配置信息图片及部分相关技术知识点来源于网络搜索,侵权删!