并自己实现一下

Overlay基本原理

Overlay文件系统类似于堆叠的文件系统,它本身不像其他传统文件系统(jffs2、ext4、fat…)那样,直接参与磁盘空间及节点存储的划分。它更像是一个皮包公司,依赖并构建于其他传统文件系统之上,“合并”底层传统文件系统中文件内容的差异并进行“合并”,然后再向用户呈现。因此用户看到的文件系统根目录,其实是overlay“合并”的文件系统目录的“合集”。

文件系统的理解,可以参考一本书的结构:
一本书有厚有很多内容(类比为磁盘空间),而每本书前面的目录(类比为文件系统),可以帮我们准确的定位到你要查找的内容在书正文的那一页(类比为文件系统inode节点)。

Docker overlay存储驱动

Docker镜像和容器

镜像(image)

是一个或几个只读层的堆叠“合并”,通过overlay文件系统“合并”成一个统一文件系统,从用户角度来看,隐藏了多个只读层的细节,只存在一个统一文件系统。

docker 中overlay2中不需要的文件如何判断 docker的overlay目录_容器

容器(Container)

跟镜像一样,也是一个或多个只读层的堆叠“合并”,只不过不同的是,最上层比镜像多了一个可读写的统一文件系统层。即:容器 = 镜像 + 可读写层;

docker 中overlay2中不需要的文件如何判断 docker的overlay目录_docker_02

相关目录

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开头的 目录,里面包含一些该容器信息。