主要是对 docker 文档(v18.03)的翻译以及自己的学习笔记
本篇主要包含以下内容
Docker 存储介绍
Docker 为容器提供了两种存放数据的资源:
- storage driver:管理的镜像层和容器层
特点:Copy-on-Write。新数据会存放在最上层容器层,修改现有数据会先从镜像层复制到容器层,修改后的数据直接保存在容器中,镜像层保持不变。若多层中有同名文件,用户只能看到最上层的文件。
可通过 docker info 查看到。Docker 优先使用默认的 storage driver。 - data volume 数据卷
特点:是目录或文件,不是磁盘,volume 数据可以被永久的保存,即使使用它的容器已经销毁。
分为两种 volume:bind mount 和 docker managed volume
存储驱动:目前 docker 支持五种存储驱动。详见存储引擎
- AUFS
- Btrfs
- Device Mapper
- Overlay
- ZFS
原理:
- Copy-On-Write 写时复制
所有驱动都是用到 Cow 写时复制(copy-on-write),只在需要写时才复制。可以让所有容器都共享一个 image 文件系统,所有数据都从 image 读取,容器需要写操作时,才将要写的文件从 image 复制到自己的文件系统,即所有写操作都是对 image 中副本的修改。有效提高了磁盘利用率。 - allocate-on-demand 用时分配
在要写入一个文件时才按需分配空间
驱动:
- AUFS:一种 Union FS 联合文件系统,文件级存储。支持将不同目录挂载到同一个虚拟文件系统,下层文件系统只可读,最上层可写。若要修改,AUFS 会创建一个该文件的副本,放在可写层,结果也保存在可写层。
- Overlay:一种 UnionFS,文件级存储。只有两层:upper 层和 lower 层
- Device Mapper:RHEL 下 Docker Engine 的默认存储驱动,基于同名级卷管理技术框架的存储引擎。
默认情况下,在容器内创建的所有文件都存储在可写容器层中,仅存储在主机系统的内存中,即tmpfs
方式,永远不会写入主机系统的文件系统,因此一旦容器停止,容器内所有文件的改动都会丢失,所以需要通过一些机制将文件保存以至于在容易停止后仍不会丢失。
docker 有三种存储容器数据的方式:
bind mount
:可将容器数据存放在宿主机的任何位置。volumes
:通过创建数据卷将容器数据持久化到文件系统。tmpfs
:数据存放在内存中,不会写入文件系统。
BindMount
bind mount
可使容器中的文件存储在主机系统的任何位置。Docker 主机或 Docker 容器上的非 Docker 进程可以随时修改它们。bind mount 非常高效,但它们依赖于具有特定目录结构的主机文件系统。
docker 提供两种选项进行 bind mount。
-v
或--volume
:三个字段组成,冒号分隔。
- 第一个字段:卷名,若是匿名卷,则可省略
- 第二个字段:文件或目录在容器中安装的路径
- 第三个字段:可选项,例如
ro
,默认是可读可写
--mount
:由多个键值对组成,用逗号分隔,键和值用=
连接。以下是提供的键:
type
:挂载的类型,可以是 bind,volume 或 tmpfs。source
或src
:挂载源,即卷名。匿名卷可省略。destination
或dst
或target
:挂载到的容器中的指定目录或文件路径readonly
:以只读方式挂载,可选。volume-opt
:卷选项,可指定多次,也是键值对形式bind-propagation
:绑定传播,有以下选择:rprivate
,private
,rshared
,shared
,rslave
,slave
注:–mount 不支持设置 selinux 的z
或Z
选项
如果使用-v
或--volume
绑定安装 Docker 主机上尚不存在的文件或目录,则-v 会为您创建端点。它始终作为目录创建。而如果使用--mount
,Docker 不会自动为您创建它,但会生成错误。
注:bind mount 允许访问敏感文件
使用 bind mount 的一个副作用:可以通过容器中运行的进程更改主机文件系统,包括创建,修改或删除重要的系统文件或目录。这是一种强大的功能,可能会产生安全隐患,包括影响主机系统上的非 Docker 进程。
当挂载一个 bind mount 或非空数据卷到容器中的一个非空目录,则该目录中原有的文件会被掩盖(并非删除),而只显示挂载的卷内容。当挂载一个空数据卷到容器中的一个非空目录,则该目录中的文件都会复制到该卷中。若启动容器时指定了一个不存在的数据卷,则会自动创建一个卷。
使用-v挂载 |
docker inspect 容器
查看是否挂载了数据卷
bind-propagation 传播挂载
在指定的 bind mount 或数据卷上挂载是否能被复制到挂载的目录中去。用于做动态,可通过编排工具方便实现。
有以下几种选项:
- shared:源挂载的子挂载会暴露给副本挂载,副本挂载的子挂载也会复制到源挂载。
- slave:类似于 shared,但只在一个方向上。如果源挂载暴露了子挂载,则副本挂载可以看到它。但是,如果副本挂载暴露了子挂载,则源装载无法看到它。
- private:此挂载是私人的。其中的子挂载不会暴露给副本挂载,副本挂载的子挂载不会暴露给源挂载。
- rshared:与 shared 相同,但传播也扩展到嵌套在任何源或副本挂载中的挂载点。
- rslave:与 slave 相同,但传播也扩展到嵌套在任何源或副本挂载中的挂载点。
- rprivate:默认值。与 private 相同,源或副本挂载中任何位置的挂载点都不会沿任一方向传播。
Selinux 标签
如果使用 selinux,则可以添加z
或Z
选项以修改要挂载到容器的主机文件或目录的 selinux 标签。这会影响主机本身上的文件或目录,并且可能会影响到 Docker 外部。
z
选项表示绑定装载内容在多个容器之间共享。Z
选项表示绑定装载内容是私有且非共享的。使用Z
选项绑定安装系统目录(例如/home
或/usr
)会导致主机无法运行。
当 bind mount 和 service 一起使用时,会自动忽略 selinux 标签(z
和Z
)还有ro
。
Volume 数据卷
卷是保存 Docker 容器生成和使用的数据的首选机制,并且卷完全由 Docker 管理。
写入容器的可写层需要存储驱动程序来管理文件系统,存储驱动程序使用 Linux 内核提供联合文件系统 UFS。而数据卷是经过特殊设计的目录,可以绕过联合文件系统,为多个容器提供访问。数据卷的目的在于数据永久化,完全独立于容器的生存周期,容器删除时挂载的数据卷不会被删除。
特点:
- 卷比 bind mount 更容易备份或迁移。
- 卷适用于 Linux 和 Windows 容器。
- 可以在多个容器之间更安全地共享卷。
- 在容器启动时初始化,若挂载点已有数据,则会被拷贝到新初始化的数据卷中
- 数据卷变化不会影响镜像更新
- 卷驱动程序允许在远程主机或云提供程序上存储卷,加密卷的内容或添加其他功能。
可通过docker volume create 数据卷名
创建数据卷。每创建一个 volume,就会在/var/lib/docker/volumes
中创建一个同名目录。若不指定数据卷名,就会随机生成一个 volume ID 作为数据卷名。
docker volume
命令
create 创建数据卷 |
在创建 volume 时或启动使用为创建卷的容器时,可以指定卷的驱动。
数据卷驱动可通过docker plugin install [选项] 驱动名
。
如果卷驱动程序要求您传递选项,则必须使用--mount
标志来装入卷
docker 提供-v
和--mount
选项进行挂载。使用与 bind mount 基本一致。
如果需要指定卷驱动程序选项,则必须使用--mount
。将卷与服务一起使用时,仅支持--mount
。
注:挂载数据卷不支持单个文件,只能是目录。且不权限控制,均为可读写。
因为容器配置文件里的可以指定docker inspect
查看,发现Mounts
中的Source
字段,其中已指定了源,源为:/var/lib/docker/volumes/容器长ID/_data
。
以上两种方法数据源其实还是宿主机中的,并不是真正放在 volume container 中,可以在通过 dockerfile 的ADD
将数据打包进镜像并指定VOLUME
,将ADD
指定的目录与VOLUME
设为一致,此法称为data-packed volume container
。
Tmpfs
使用tmpfs mount
创建容器时,容器可以在容器的可写层之外创建文件。tmpfs 挂载是临时的,仅保留在主机内存中。当容器停止时,将删除 tmpfs 挂载,该数据不可被共享,Docker 默认使用 tmpfs 挂载。--tmpfs
:安装 tmpfs 挂载而不允许指定任何可配置选项,并且只能与独立容器一起使用。
也可以通过--mount
指定type=tmpfs
。
数据卷容器
容器挂载数据卷,其他容器通过挂载该容器实现数据共享,挂载数据卷的容器称为数据卷容器。
创建容器时--volumes-from 数据卷容器
创建数据卷容器
注:由于数据卷容器仅是提供数据,所以只要 create,不用 rundocker rm -v 容器
在删除容器时一并删除数据卷。但是,只要有容器还在使用该数据卷,数据卷就不会删除。宿主机上的数据卷若删除,就真的没了。
> docker volume create volume_1 |
数据卷备份、还原与迁移
使用数据卷能方便地进行数据备份、迁移和还原。
备份一个容器
首先创建一个数据卷,用于存放备份数据。docker volume create vol_backup
然后创建一个数据卷容器,挂载该数据卷
docker create --name backup_container\ |
接着运行要备份容器,挂载数据卷容器 backup_container,并将要备份的数据打包放入数据卷。
docker run --rm \ |
在主机的/var/lib/docker/volumes/vol_backup/_data/
中出现了打包后的data.tar
还原一个容器
docker run --rm \ |
删除一个数据卷
删除的数据卷有两种情况:
- 命名卷在容器外部有指定源,删除了容器,数据卷并不会被删除
- 匿名卷没有指定源,在删除容器时,该匿名卷也会被删除。也可在创建容器时,加上
--rm
参数,关闭时自动删除容器和匿名卷。
存储引擎
参考资料
Docker 官方文档-存储
每天 5 分钟玩转 docker 容器技术