容器存储
docker为容器准备了两种存放数据的方法
1、docker storage driver 管理的镜像层和容器层
2、data volume
storage driver
容器由最上面的容器层和若干数量的只读镜像层组成,容器的数据就存放在这些层中。
这样分层结构的最大特性是 copy-on-write
- 新数据会放在最上层的容器层中
- 修改原有镜像层的数据,会将镜像层中的数据复制到容器层,修改后的数据就保存在容器层中,镜像层的数据保持不变。
- 如果多个层中有命名相同的文件,用户只能看到最上一层的那个文件
分层结构使构建镜像和容器的创建共享、分发变得高效
storage driver 实现了多层数据的堆叠并为用户提供了一个单一合并之后的视图
docker 支持多种 storage driver
- AUFS
- Device Mapper
- Btrfs
- OverlayFS
- VFS
- ZFS
他们都支持分层的架构,同时有拥有不同的特性
1、没有drvier可以适用所有场景
2、drvier本身在快速迭代
docker 安装时会根据当前系统的配置选择默认的driver
运行# docker info
可以查看
Server Version: 17.12.1-ce
Storage Driver: overlay2
Backing Filesystem: extfs
对于某些容器,直接将数据放在storage driver 维护的层中,比如无状态的应用。无状态意味着没有需要持续化的数据,随时从镜像中直接创建
data volume
Data Volume本质上是 docker host文件系统内的目录或文件,能够被直接mount到容器文件系统中
1、data volume是目录或文件,而非没有格式化的磁盘(块设备
2、容器可以读写 volume 中的数据
3、volume的数据可以被永久保存,即使使用它的容器已经被销毁
如何选择数据存储方式
1、database 软件 databases数据
2、web 应用 web应用产生的日志
3、Apache server 静态HTML文件
无状态的应该作为镜像的一部分,需要持续化的数据应该与镜像分开存放
docker volume 提供了两种方式
bind mount
将host文件系统上已存在的目录或文件mount到容器
# docker run -d -p 8080:80 -v /data/html:/usr/local/apache2/htdocs httpd
-v 的格式为
# docker run -d -p 9999:80 -v /data/html:/usr/local/apache2/htdocs:ro httpd
还可以指定读写权限
bind mount的使用直观高效易于理解 但是需要指定host文件系统的特定路径,这样就限制了容器的可移植性
docker managed volume
Managed volume 和 bind mount 最大的区别是不需要指定mount源 指明mount point就可以了
# docker run -d -p 8080:80 --name=httpd_8080 -v /usr/local/apache2/htdocs httpd
通过-v 告诉容器我们需要data volume(数据卷) 并将其挂载到容器指定位置
docker 数据卷的位置 /var/lib/docker/volumes/
# docker inspect
命令结果的mounts区域里显示了mount的详细信息
# docker volume ls
数据卷列表
# docker volume inspect
数据卷详情 命令的对象为数据卷
如果volume 挂载到容器中有已经有数据的目录,原有的数据会被复制到volume中
但此时容器中挂载的数据已经不是storage driver管理的层数据了
数据共享
容器与host数据共享
bind mount 直接将要共享的目录直接mount到容器
managed volume 就需要在容器创建后生成了mount路径 再进行数据复制
容器与容器之间数据共享
1、将数据放在bind mount 目录中,然后将其mount到多个容器中
2、volume container
volume container是用来为其他容器提供volume的容器。他提供的卷可以是bind mount 也可以是managed volume的
# docker create --name=data_vc -v /data/:/usr/local/apache2/htdocs -v /root/data busybox
创建一个volume container 不需要运行 ;
# docker volume ls
查看卷列表
# docker run -d -p 8888:80 --name=httpd0 --volumes-from data_vc httpd
# docker run -d -p 9999:80 --name=httpd1 --volumes-from data_vc httpd
创建httpd容器并指定使用data_vc容器为volume container (以data_vc为模版)
# 检查httpd容器是否关联,并再次查看卷列表,没有新增的volume
# docker inspect httpd
检查容器的mounts区域配置。发现httpd容器的配置与data_vc一致
与 bind mount 相比,不必为每一个容器指定 host path,所有 path 都在 volume container 中定义好了,容器只需与 volume container 关联,实现了容器与 host 的解耦。使用 volume container 的容器其 mount point 是一致的,有利于配置的规范和标准化,但也带来一定的局限,使用时需要综合考虑
data-packed volume container
Volume container 中数据还是在host中
data-packed volume container 其原理就是将数据打包到镜像中,通过docker managed volume 共享
# vim dockerfile
FROM busybox
ADD htdocs /usr/local/apache2/htdocs 复制到镜像层
VOLUME /usr/local/apache2/htdocs 将数据同步到host
# docker build -t datapacked .
构建镜像
# docker create --name vc_data datapacked
创建模版容器
# docker run -d -p 1111:80 --volumes-from vc_data httpd
启动容器并指定volume
volume生命周期管理
volume的创建、共享和使用
备份、恢复、迁移、销毁volume
备份##########
因为volume实际上是host文件系统中的目录和文件,备份volume实际上就是对文件系统的备份
恢复
迁移
假如使用更高版本的Registry,这就涉及数据迁移的问题
1、 docker stop 停止当前容器
2、启动新版本容器并mount原有volume
docker run -d -p 5000:5000 -v /myregistry:/var/lib/registry registry:latest
销毁
可以删除不再需要的volume,但是无法找回了
docker不会销毁bind mount ,删除数据的工作只能由host负责。
对于docker managed volume
,在执行 # docker rm
删除容器时可以带上-v
参数 ,docker 会将容器使用到的volume一并删除
但前提是没有其他容器mount该volume,目的是保护数据
如果删除容器时没有带有 -v 选项 docker的volume就会遗留下来。
可以通过 docker volume ls
查看全部的volume
# docker volume rm xxx xxx
批量删除
# docker volume rm $(docker volume ls -q)