并自己实现一下
Overlay基本原理
Overlay文件系统类似于堆叠的文件系统,它本身不像其他传统文件系统(jffs2、ext4、fat…)那样,直接参与磁盘空间及节点存储的划分。它更像是一个皮包公司,依赖并构建于其他传统文件系统之上,“合并”底层传统文件系统中文件内容的差异并进行“合并”,然后再向用户呈现。因此用户看到的文件系统根目录,其实是overlay“合并”的文件系统目录的“合集”。
文件系统的理解,可以参考一本书的结构:
一本书有厚有很多内容(类比为磁盘空间),而每本书前面的目录(类比为文件系统),可以帮我们准确的定位到你要查找的内容在书正文的那一页(类比为文件系统inode节点)。
Docker overlay存储驱动
Docker镜像和容器
镜像(image)
是一个或几个只读层的堆叠“合并”,通过overlay文件系统“合并”成一个统一文件系统,从用户角度来看,隐藏了多个只读层的细节,只存在一个统一文件系统。
容器(Container)
跟镜像一样,也是一个或多个只读层的堆叠“合并”,只不过不同的是,最上层比镜像多了一个可读写的统一文件系统层。即:容器 = 镜像 + 可读写层;
相关目录
docker目录下:
[root@tencent2c2g docker]# ls
buildkit containers engine-id image network overlay2 plugins runtimes swarm tmp volumes
containers: 容器相关的信息存储目录
image : 镜像相关的信息存储目录
- image/overlay2/imagedb:镜像信息及镜像layer各个层信息;
- image/overlay2/layerdb:镜像各个layer层的信息(imagedb sha256sum)
overlay2:docker镜像内,镜像各个layer中具体的文件内容及数据;
image 目录
拉取nginx镜像实验
1、拉取nginx镜像
[root@tencent2c2g ]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete
a9edb18cadd1: Pull complete
589b7251471a: Pull complete
186b1aaa4aa6: Pull complete
b4df32aa5a72: Pull complete
a0bcbecc962e: Pull complete
Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
可以看到拉取了六个只读层文件
[root@tencent2c2g sha256]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 14 months ago 141MB
2、 进入:/var/lib/docker/image/ overlay2/imagedb/content/sha256
可以看到 以IMAGE ID开头的 文件605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85
查看文件:以 以下结尾
……"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f","sha256:e379e8aedd4d72bb4c529a4ca07a4e4d230b5a1d3f7a61bc80179e8f02421ad8","sha256:b8d6e692a25e11b0d32c5c3dd544b71b1085ddc1fddad08e68cbd7fda7f70221","sha256:f1db227348d0a5e0b99b15a096d930d1a69db7474a1847acbc31f05e4ef8df8c","sha256:32ce5f6a5106cc637d09a98289782edf47c32cb082dc475dd47cbf19a4f866da","sha256:d874fd2bc83bb3322b566df739681fbd2248c58d3369cb25908d
结尾处,“diff_ids”: 得到6个layer id 从头到尾分别对应 image从底层到顶层
3、前往/var/lib/docker/image/ overlay2/layerdb/sha256
查看每层layer信息
[root@tencent2c2g sha256]# ls
02b80ac2055edd757a996c3d554e6a8906fd3521e14d1227440afd5163a5f1c4 7850d382fb05e393e211067c5ca0aada2111fcbe550a90fed04d1c634bd31a14
2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f b625d8e29573fa369e799ca7c5df8b7a902126d2b7cbeb390af59e4b9e1210c5
780238f18c540007376dd5e904f583896a69fe620876cabc06977a3af4ba4fb5 b92aa5824592ecb46e6d169f8e694a99150ccef01a2aabea7b9c02356cdabe7c
可以看到 (2、)中文件中得到的 6 个layer id 中最底层(第一个)的id
这是因为 :
docker使用了sha256sum方式去保存这些layer及image id,则sha256:3cbe18655eb6…这个image id的上一层id是echo -n "sha256:3cbe18655eb6...[diff_ids json数组最底层id] sha256:84cc[diff_ids json数组倒数第二层id]" | sha256sum-,那么上上一层id是上一步得出的结果和diff_ids json数组倒数第三层id一起计算sha256sum得出,以此类推,如下图的方式,可以看出各个layer已经全部对应上了。
即 倒数第二层 为 其下一层与倒数第二层 进行sum所得;
4、查看其6个目录,其格式除 最底层文件没有parent外,其他均为以下形式文件
./780238f18c540007376dd5e904f583896a69fe620876cabc06977a3af4ba4fb5
./780238f18c540007376dd5e904f583896a69fe620876cabc06977a3af4ba4fb5/cache-id
./780238f18c540007376dd5e904f583896a69fe620876cabc06977a3af4ba4fb5/tar-split.json.gz
./780238f18c540007376dd5e904f583896a69fe620876cabc06977a3af4ba4fb5/diff
./780238f18c540007376dd5e904f583896a69fe620876cabc06977a3af4ba4fb5/parent
./780238f18c540007376dd5e904f583896a69fe620876cabc06977a3af4ba4fb5/size
其中cache-id 为镜像每层真正数据存储的目录,在docker/overlay/{cache-id}里
overlay目录
5、前往该目录
[root@tencent2c2g 13f04157d45fbcc829febc064571efc77229e34baffe477866e5defdd894db7a]# ls
committed diff link lower work
diff中存储的是下层与本层的合并
挨个查看可以证实合并,例如其中两个:
[root@tencent2c2g overlay2]# cat dea4d40f12e51dd8447a2ba580c80ecd7730b040c5279a3a8980833e3b8d8c13/diff/
docker-entrypoint.d/ etc/ lib/ tmp/ usr/ var/
[root@tencent2c2g overlay2]# cat 717f3beb6604e0a55de465b766f4163ffe3eefe06e224ed595d6f093f067650f/diff/
bin/ boot/ dev/ etc/ home/ lib/ lib64/ media/ mnt/ opt/ proc/ root/ run/ sbin/ srv/ sys/ tmp/ usr/ var/
container目录
首先运行一个容器
docker run -it --name=test nginx:latest /bin/bash
进入容器,
新建一个文件:
root@fb0fce6e93e8:/# touch touch ttttfile
root@fb0fce6e93e8:/# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp touch ttttfile usr var
退出后前往overlay2目录查看,可以看到两个新增的目录
ceb6cc8f85e57449922f707ef9378ddb03ef2eeab0b0d0dadf2ffdec66857a77-init
ceb6cc8f85e57449922f707ef9378ddb03ef2eeab0b0d0dadf2ffdec66857a77
查看其中的diff,有 刚刚创建的文件,且包含文件内容
[root@tencent2c2g diff]# ls
root ssss testfile
并在可以在container目录下 有该容器id开头的 目录,里面包含一些该容器信息。