Docker存储驱动程序
目前docker的默认存储引擎为overlay2,不同的存储引擎需要相应的文件系统支持,如需要磁盘分区的时候传递d-type稳健分层功能,即需要传递内核参数并开启格式化磁盘的时候指定的功能
- 历史更新信息
https://github.com/moby/moby/blob/master
- 存储引擎的选择文档
https:/docs.docker.com/storage/storagedriver/select-storage-driver/
容器和层
我们构建 Docker 镜像一般采用 Dockerfile 的方式,而 Dockerfile 的每行命令,其实就会生成一个“层”,即使什么文件都没有添加。
FROM ubuntu:15.04
COPY . /app
RUN make /app
CMD python /app/app.py
Docker 的镜像(image)是静态的,所以当镜像构建完成后,所有的层都是只读的,并会赋予一个唯一的 ID。而容器(container)是动态的,当容器启动后,Docker 会给这个容器创建一个可读写“层”,位于所有镜像“层”的最上面。我们对容器的所有操作也就是在这个“层”里完成,当我们执行 docker commit
将容器生成镜像的时候,就是把这个“层”给拍了个快照,添加了一个新的只读层。
文件的创建是在读写层增加文件,那修改和删除呢?
这就要提一下 Docker 设计的 copy-on-write (CoW) 策略。
当我们试图读取一个文件时,Docker 会从上到下一层层去找这个文件,找到的第一个就是我们的文件。所以下面层相同的文件就被“覆盖”了。而修改就是当我们找到这个文件时,将它“复制”到读写层并修改,这样读写层的文件就是我们修改后的文件,并且“覆盖”了镜像中的文件了。而删除就是创建了一个特殊的 whiteout
文件,这个 whiteout
文件覆盖的文件即表示删除了。
这样的设计有什么好处吗?
显而易见的就是减少了存储空间,由于镜像被分成了多个层,而各个层是静态只读的,是可以共享的。当你从一个镜像构建另一个镜像时,只需要添加新的层,原有的层不会被复制。
我们可以用 docker history
命令查看我们创建的镜像,相同的层将共享且只保存一份。
我们可以在系统的 /var/lib/docker/<存储驱动>/
下看到我们所有的层。
第二个好处是启动容器就变得非常轻量和快速。因为我们的容器只是添加了一个“空”的读写层,其他的都是复用的只读层,需要用时才会去搜索。
存储驱动
存储驱动类型
AUFS
AUFSAnotherUnionFileSystem
是一种UnionFS。V2版本后更名为 advanced multi‐layered unification fileystem,即高级多层统一文件系统。所谓UnionFS就是把不同物理位置的目录合并mount到同一个目录中。简单来说就是支持将不同目录挂载到同一个虚拟文件系统下的文件系统。这种系统可以一层一层的叠加修改文件。无论底下有多少层都是只读,只有最上层的文件系统是可读写。当需要修改一个文件时,AUFS创建该文件的一个副本。使用CoWCopy-on-Write
将文件从只读层复制到可写层进行修改,结果也保留在可写层、在Docker中。底下的制度层就是image,可写层就是Container。
在 Ubuntu 14.04 系统上现有如下目录结构:
$ tree
.
├── fruits
│ ├── apple
│ └── tomato
└── vegetables
├── carrots
└── tomato
输入以下几个命令:
# 创建一个mount目录
$ mkdir mnt
# 把水果目录和蔬菜目录union mount到 ./mnt目录中
$ sudo mount -t aufs -o dirs=./fruits:./vegetables none ./mnt
# 查看./mnt目录
$ tree ./mnt
./mnt
├── apple
├── carrots
└── tomato
我们来修改一下其中的文件内容:
$ echo mnt > ./mnt/apple
$ cat ./mnt/apple
mnt
$ cat ./fruits/apple
mnt
上面的示例,我们可以看到./mnt/apple的内容改了,./fruits/apple的内容也改了。
$ echo mnt_carrots > ./mnt/carrots
$ cat ./vegetables/carrots
$ cat ./fruits/carrots
mnt_carrots
AUFS是Docker18.06及更早版本的首选存储驱动程序,在内核3.13上运行Unbantu14.04时不支持overlay2
Overlay
一种Union FS文件系统,Linux内核3.18后支持
Overlay2
overlay的升级版,到目前为止,所有Linux发行版推荐使用的存储类型
devicemapper
是CentOS和RHEL的推荐存储驱动程序,但是依赖于direct-lvm
,存在空间受限的问题,虽然可以通过后期配置解决;因为之前的内核版本不支持overlay2(集中在Centos/RHEL7.2之前版本);但当前较新版本Centos和RHEL现已经支持overlay2。
https://www.cnblogs.com/youruncloud/p/5736718.html
zfs/btrfs(Oracle-2007)
目前没有广泛应用;这些文件系统允许使用高级选项,例如创建“快照”,但需要更多的维护和设置。并且每一个都依赖于正确配置的后备文件系统。
vfs
用于测试环境,适用于无法适用Cow文件系统的情况。此存储驱动程序的性能很差,通常不建议在生产中使用。
Linux发行版 | 推荐的存储驱动程序 | 替代驱动 |
---|---|---|
Docker Engine-Ubuntu上的社区 | overlay2 或aufs (对于在内核3.13上运行的Ubuntu 14.04) |
overlay ,devicemapper zfs ,vfs |
Docker Engine-Debian上的社区 | overlay2 (Debian Stretch)aufs 或devicemapper (旧版本) |
overlay , vfs |
Docker Engine-CentOS上的社区 | overlay2 |
overlay ,devicemapper zfs ,vfs |
Docker Engine-Fedora上的社区 | overlay2 |
overlay ,devicemapper zfs ,vfs |
1)overlay
存储驱动程序已在Docker Engine-Enterprise 18.09中弃用,并将在以后的版本中删除。建议将overlay
存储驱动程序的用户迁移到overlay2
。
2)devicemapper
存储驱动程序已在Docker Engine 18.09中弃用,并将在以后的版本中删除。建议将devicemapper
存储驱动程序的用户迁移到overlay2
。
建议使用overlay2
存储驱动程序。首次安装Docker时,默认情况下使用overlay2
。早期版本,默认情况下会使用aufs
。如果要在新版本中使用aufs
,则需要对其配置,并且可能需要安装其他软件包,例如linux-image-extra
。
支持的文件系统
对于Docker,支持文件系统是所在的文件系统 /var/lib/docker/
。一些存储驱动程序仅适用于特定的后备文件系统。
存储驱动 | 支持的后备文件系统 |
---|---|
overlay2 , overlay |
xfs 在ftype = 1的情况下, ext4 |
aufs |
xfs , ext4 |
devicemapper |
direct-lvm |
btrfs |
btrfs |
zfs |
zfs |
vfs |
任何文件系统 |
overlay2
,,aufs
和overlay
都在文件级别而不是块级别运行。这样可以更有效地使用内存,但是在写繁重的工作负载中,容器的可写层可能会变得非常大。- 块级存储驱动器,例如
devicemapper
,btrfs
和zfs
更好地为写繁重的工作负担(虽然不如Docker volumes)执行。 - 对于许多小型写入或具有多层或深文件系统的容器,其性能
overlay
可能比更好overlay2
,但会消耗更多的inode,这可能导致inode耗尽。 btrfs
并zfs
需要大量内存。zfs
对于高密度工作负载(例如PaaS)是一个不错的选择。
如果docker 数据目录是一块单独的磁盘分区而且是xfs格式的,那么需要在格式化的时候加上参数 -n ftype=1,否则后期在启动容器的时候会报错不支持dtype 。
报错界面:
修改更换存储引擎
配置 Docker 存储驱动非常简单,只需要修改配置文件即可。
注意:如果你原先有不同存储驱动的层数据,更换存储驱动后将不可用,建议备份镜像并清除
/var/lib/docker
下所有数据。备份镜像可以用
docker save
导出镜像,之后用docker load
导入镜像。
修改前现先fdisk -l
查看文件系统类型
摘掉挂载umount /var/lib/docker
注意:可能会出现
umount: /var/lib/docker: target is busy.
关闭占用进程
fuser -km /var/lib/docker
(慎用fuser -km
)。在psmisc
包中yum install psmisc -y
或者systemctl stop docker再次进行卸载
对文件系统进行类型格式化mkfs.xfs -n ftype=1 /dev/sdX
ormkfs.ext4 /dev/sdX
再次进行挂载mount /dev/sdX /var/lib/docker
创建或修改文件 /etc/docker/daemon.json
并添加
{
"storage-driver": "overlay2"
}
然后重启 Docker
systemctl restart docker
或者
#修改/lib/systemd/system/docker.service
......
ExecStart=/usr/bin/dockerd -s=overlay2
......
然后重启 Docker
systemctl daemon-reload
systemctl restart docker