Docker 联合文件系统(Union File System)

目录

简介

CentOS OverlayFS 实验

Docker Image结构拆解

一层Layer

二层Layer        

三层Layer

Docker容器使用overlayFS


简介

        Docker使用Union File System(联合文件系统)技术来构建容器的文件系统。

        联合文件系统能够将不同的目录层(层次)叠加在一起,形成单一一致的文件系统视图。

        Docker的每个镜像由一系列的只读层组成,当运行一个容器时,Docker在这些只读层的顶端叠加一个可写层,并且所有对文件系统的改变都会记录在这个可写层中。

        Docker镜像的每一层都对应一个文件系统的改动集合,例如安装一个软件包或者添加一个文件等。

        当你构建一个新的镜像时,每条RUN指令都会创建一个新的层。文件系统层是共享的,相同的层可以在多个镜像之间共享,这样可以节省磁盘空间,并且使得镜像推送和拉取更加高效。

  1. 基础镜像层: 假设有一个Ubuntu镜像,它包含了操作系统的基础层,这些层是只读的。

  2. 中间层: 接下来,用户基于基础镜像创建自己的镜像,可能会添加一些软件包或应用程序。每个操作会创建一个新的只读层。

  3. 可写层: 当容器启动时,Docker在最顶层添加一个可写层,这个是容器层。所有对容器文件系统的更改都会在这个层上进行。如果容器被删除,这个层也随之被删除,但是下面的层依然不变。

  4. 数据卷(Volumes): 对于需要持久化或者共享的数据,Docker提供了数据卷的概念。数据卷是存在于宿主机上的目录或文件,可以直接挂载到容器内部。数据卷不属于联合文件系统的一部分,它们绕过Union File System直接进行数据的存取。

CentOS OverlayFS 实验

        在 CentOS 系统上测试联合文件系统,比如 OverlayFS(Overlay2 是 Docker 针对 OverlayFS 的实现),OverlayFS 支持在较新版本的 Linux 内核中通常是内置的

# 1. 创建 OverlayerFS 不同的层
> mkdir -p /opt/overlayer-test
# 1.1 只读底层
> mkdir -p /opt/overlayer-test/lower            
# 1.2 可写上层
> mkdir -p /opt/overlayer-test/upper
# 1.3 工作目录,用于 OverlayFS 的内部机制。
> mkdir -p /opt/overlayer-test/work
# 1.4 合并点,你将在这里看到上层和底层的统一视图。
> mkdir -p /opt/overlayer-test/merged

#2. 创建并填充文件
> echo "this is a file in lower layer" > /opt/overlayer-test/lower/lowerfile.txt

#3. 挂载 OverlayFS, 使用 mount 命令将 lower 和 upper 目录合并到 merged 目录:
> mount -t overlay overlay -o lowerdir=/opt/overlayer-test/lower,upperdir=/opt/overlayer-test/upper,workdir=/opt/overlayer-test/work /opt/overlayer-test/merged

#4. 
#4.1 现在,如果你查看 /opt/overlayer-test/merged 目录,你应该能够看到来自 lower 目录的文件:
> ls -l /opt/overlayer-test/merged
总用量 4
-rw-r--r-- 1 root root 12 3月   6 01:52 lowerfile.txt
> cat /opt/overlayer-test/merged/lowerfile.txt
this is a file in lower layer

#4.2 在 merged 目录中创建文件,它将出现在 upper 目录中:
> echo "this file will be in upper layer" > /opt/overlayer-test/merged/upperfile.txt

> ls -l /opt/overlayer-test/upper/
总用量 4
-rw-r--r-- 1 root root 33 3月   6 01:56 upperfile.txt

#4.3 删除或修改 merged 目录中的文件,这些操作将反映在 upper 目录中,而 lower 目录保持不变:
> echo "this lower layer changed, will be in upper layer" > /opt/overlayer-test/merged/lowerfile.txt

> ls -l /opt/overlayer-test/lower/
总用量 4
-rw-r--r-- 1 root root 12 3月   6 01:52 lowerfile.txt
> cat /opt/overlayer-test/lower/lowerfile.txt
this is a file in lower layer

> ls -l /opt/overlayer-test/upper/
总用量 8
-rw-r--r-- 1 root root 49 3月   6 02:00 lowerfile.txt
-rw-r--r-- 1 root root 33 3月   6 01:58 upperfile.txt
> cat /opt/overlayer-test/upper/lowerfile.txt
this lower layer changed, will be in upper layer

#5. 
umount /opt/overlayer-test/

Docker Image结构拆解

        Docker文件系统正式利用了联合系统的特性,分层存储,共用相同的Layer,优化存储空间。

一层Layer
# 1. 查看alpine:3.15的layers.
# 1.1 使用docker inspect命令查询  --> 说明只有一层Layer
> docker inspect alpine:3.15
[
  {
    "Id":"sha256:0ac33e5f5afa79e084075e8698a22d574816eea8d7b7d480586835657c3e1c8b"
    ...
    "RootFS":{
      "Type": "layers",
      "Layers":[
        "sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628"
      ]
    }
    ...
  }
]
# 1.2 通过ImageID,查询Image元数据文件 ImageId --> 0ac33e5f5afa79e084075e8698a22d574816eea8d7b7d480586835657c3e1c8b
> cat /var/lib/docker/image/overlay2/imagedb/content/sha256/0ac33e5f5afa79e084075e8698a22d574816eea8d7b7d480586835657c3e1c8b  | python -m json.tool
{
...
  "rootfs":{
    "diff_ids": [
      "sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628"
    ],
    "type": "layers"
  }
...
}

#2. 根据DiffID 从LayerDB元数据中,查询事件的LayerID
> cat /var/lib/docker/image/overlay2/layerdb/sha256/4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628/cache-id

ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78

#3. 根据LayerID ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78, 查询Layer的文件 
> ls -l /var/lib/docker/overlay2/ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78/diff/
总用量 12
drwxr-xr-x  2 root root 4096 4月   4 2022 bin
drwxr-xr-x  2 root root    6 4月   4 2022 dev
drwxr-xr-x 16 root root 4096 4月   4 2022 etc
drwxr-xr-x  2 root root    6 4月   4 2022 home
drwxr-xr-x  7 root root  247 4月   4 2022 lib
drwxr-xr-x  5 root root   44 4月   4 2022 media
drwxr-xr-x  2 root root    6 4月   4 2022 mnt
drwxr-xr-x  2 root root    6 4月   4 2022 opt
dr-xr-xr-x  2 root root    6 4月   4 2022 proc
drwx------  2 root root    6 4月   4 2022 root
drwxr-xr-x  2 root root    6 4月   4 2022 run
drwxr-xr-x  2 root root 4096 4月   4 2022 sbin
drwxr-xr-x  2 root root    6 4月   4 2022 srv
drwxr-xr-x  2 root root    6 4月   4 2022 sys
drwxrwxrwt  2 root root    6 4月   4 2022 tmp
drwxr-xr-x  7 root root   66 4月   4 2022 usr
drwxr-xr-x 12 root root  137 4月   4 2022 var
diffID

chainID[n] = sha256sum(chainID[n-1] diffID)

layerId
/var/lib/docker/image/overlay2/layerdb/sha256/${chainID}/cache-id
diff
sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa06284fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78ls -l /var/lib/docker/overlay2/ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78/diff/
总用量 12
drwxr-xr-x  2 root root 4096 4月   4 2022 bin
drwxr-xr-x  2 root root    6 4月   4 2022 dev
drwxr-xr-x 16 root root 4096 4月   4 2022 etc
drwxr-xr-x  2 root root    6 4月   4 2022 home
drwxr-xr-x  7 root root  247 4月   4 2022 lib
drwxr-xr-x  5 root root   44 4月   4 2022 media
drwxr-xr-x  2 root root    6 4月   4 2022 mnt
drwxr-xr-x  2 root root    6 4月   4 2022 opt
dr-xr-xr-x  2 root root    6 4月   4 2022 proc
drwx------  2 root root    6 4月   4 2022 root
drwxr-xr-x  2 root root    6 4月   4 2022 run
drwxr-xr-x  2 root root 4096 4月   4 2022 sbin
drwxr-xr-x  2 root root    6 4月   4 2022 srv
drwxr-xr-x  2 root root    6 4月   4 2022 sys
drwxrwxrwt  2 root root    6 4月   4 2022 tmp
drwxr-xr-x  7 root root   66 4月   4 2022 usr
drwxr-xr-x 12 root root  137 4月   4 2022 var
二层Layer        

        以一层Layer的alpine:3.15 构建二层Layer

# 1.启动容器
> docker run -it --name layer_1 alpine:3.15 sh
>> echo "add new layer 1" > /opt/layer_demo.txt
>> exit

# 2. commit方式生成image
> docker commit layer_1 alpine:3.15-layer1
sha256:1c891e0017f5b69544e9e5e82697774fa444deb4ce1bb184e0e777e6dc0df1f0   # ImageID

# 3.
> docker inspect alpine:3.15-layer1
[
    {
        "Id": "sha256:1c891e0017f5b69544e9e5e82697774fa444deb4ce1bb184e0e777e6dc0df1f0",
        ...
        ...
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628",
                "sha256:e912ed62f30d74714890b9c9effefe2ac53a9a3af3728b0dadb538b7ab03df77"
            ]
        }
    }
]


#4. 对比 alpine:3.15,共用了基础镜像Layer sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628, 仅仅新增了sha256:e912ed62f30d74714890b9c9effefe2ac53a9a3af3728b0dadb538b7ab03df77 

#5. 查看下新增Layer里面的内容,具体是什么?
#5.1 /var/lib/docker/image/overlay2/layerdb/sha256/ 下并不存在新的chainID对应的数据,
#5.2 保存了镜像层的关联关系
#5.3 最底层的Layer,是没有父Layer的,那么diffID = chainID
#5.4 否则,chainID[n] = sha256sum(chainID[n-1]  diffID[n])


> echo -n "sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628 sha256:e912ed62f30d74714890b9c9effefe2ac53a9a3af3728b0dadb538b7ab03df77" | sha256sum - | awk '{print $1}'
0214ea74c08d5c79126342265ab19e9f466ed1b9c6dcf370e3a3b3f6d2e9c42a

> ls -l /var/lib/docker/image/overlay2/layerdb/sha256/0214ea74c08d5c79126342265ab19e9f466ed1b9c6dcf370e3a3b3f6d2e9c42a/
总用量 20
-rw-r--r-- 1 root root  64 5月   6 2022 cache-id
-rw-r--r-- 1 root root  71 5月   6 2022 diff
-rw-r--r-- 1 root root  71 5月   6 2022 parent
-rw-r--r-- 1 root root   1 5月   6 2022 size
-rw-r--r-- 1 root root 324 5月   6 2022 tar-split.json.gz

## 实际的LayerID存放在对应的 cache-id文件中
> cat /var/lib/docker/image/overlay2/layerdb/sha256/0214ea74c08d5c79126342265ab19e9f466ed1b9c6dcf370e3a3b3f6d2e9c42a/cache-id
255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f 

> ls -l /var/lib/docker/overlay2/255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f/diff/
总用量 0
drwxr-xr-x 2 root root 28 3月   6 03:23 opt
drwx------ 2 root root 26 3月   6 03:23 root

> ls -l /var/lib/docker/overlay2/255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f/diff/opt/
总用量 4
-rw-r--r-- 1 root root 16 3月   6 03:23 layer_demo.txt

> cat /var/lib/docker/overlay2/255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f/diff/opt/layer_demo.txt
add new layer 1
diffID

chainID[n] = sha256sum(chainID[n-1] diffID)

layerId
/var/lib/docker/image/overlay2/layerdb/sha256/${chainID}/cache-id
diff
sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa06284fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78ls -l /var/lib/docker/overlay2/ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78/diff/
总用量 12
drwxr-xr-x  2 root root 4096 4月   4 2022 bin
drwxr-xr-x  2 root root    6 4月   4 2022 dev
drwxr-xr-x 16 root root 4096 4月   4 2022 etc
drwxr-xr-x  2 root root    6 4月   4 2022 home
drwxr-xr-x  7 root root  247 4月   4 2022 lib
drwxr-xr-x  5 root root   44 4月   4 2022 media
drwxr-xr-x  2 root root    6 4月   4 2022 mnt
drwxr-xr-x  2 root root    6 4月   4 2022 opt
dr-xr-xr-x  2 root root    6 4月   4 2022 proc
drwx------  2 root root    6 4月   4 2022 root
drwxr-xr-x  2 root root    6 4月   4 2022 run
drwxr-xr-x  2 root root 4096 4月   4 2022 sbin
drwxr-xr-x  2 root root    6 4月   4 2022 srv
drwxr-xr-x  2 root root    6 4月   4 2022 sys
drwxrwxrwt  2 root root    6 4月   4 2022 tmp
drwxr-xr-x  7 root root   66 4月   4 2022 usr
drwxr-xr-x 12 root root  137 4月   4 2022 var
sha256:e912ed62f30d74714890b9c9effefe2ac53a9a3af3728b0dadb538b7ab03df770214ea74c08d5c79126342265ab19e9f466ed1b9c6dcf370e3a3b3f6d2e9c42a255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f

ls -l /var/lib/docker/overlay2/255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f/diff/
总用量 0
drwxr-xr-x 2 root root 28 3月   6 03:23 opt
drwx------ 2 root root 26 3月   6 03:23 root


ls -l /var/lib/docker/overlay2/255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f/diff/opt/
总用量 4
-rw-r--r-- 1 root root 16 3月   6 03:23 layer_demo.txt

三层Layer

        在二层Layer上再构建一层,修改/opt/layer_demo.txt文件内容,看第二层Layer中的/opt/layer_demo.txt文件的内容是否有变化?

# 1.启动容器
> docker run -it --name layer_2 alpine:3.15-layer1 sh
>> ls -l /opt/
-rw-r--r--    1 root     root            16 Mar  6 03:23 layer_demo.txt
>> cat /opt/layer_demo.txt
add new layer 1
>> echo "add new layer 2" >> /opt/layer_demo.txt
>> cat /opt/layer_demo.txt
add new layer 1
add new layer 2
>> exit

# 2. commit方式生成image
> docker commit layer_2 alpine:3.15-layer2
sha256:1aa49089061434452497046d68947b9161e6ec4e1cba2cd9cdb6ccfaf42364ce   # ImageID

# 3.
> docker inspect alpine:3.15-layer2
[
    {
        "Id": "sha256:1aa49089061434452497046d68947b9161e6ec4e1cba2cd9cdb6ccfaf42364ce",
        ...
        ...
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628",
                "sha256:e912ed62f30d74714890b9c9effefe2ac53a9a3af3728b0dadb538b7ab03df77",
                "sha256:a6e688425ad885c2a4f39ebdd5fc30ad41042fb2409d7184aa296abc88a160d2"
            ]
        }
    }
]


#4. 对比 alpine:3.15-layer1,共用了2层Layer sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628、sha256:e912ed62f30d74714890b9c9effefe2ac53a9a3af3728b0dadb538b7ab03df77 仅仅新增了sha256:a6e688425ad885c2a4f39ebdd5fc30ad41042fb2409d7184aa296abc88a160d2 

#5. 查看下新增Layer里面的内容,具体是什么?应该共用了layer1,所以内容肯定不会变,只需要看layer2里面的文件变成什么?

# 5.1 计算chainID
> echo -n "sha256:0214ea74c08d5c79126342265ab19e9f466ed1b9c6dcf370e3a3b3f6d2e9c42a sha256:a6e688425ad885c2a4f39ebdd5fc30ad41042fb2409d7184aa296abc88a160d2" | sha256sum
e9e6b8bf5c8da3818651580ac99dd83c56ba3e8569804209a766b30fc9a2d613 | awk '{print $1}'
e9e6b8bf5c8da3818651580ac99dd83c56ba3e8569804209a766b30fc9a2d613

# 5.2 读取layerID
> cat /var/lib/docker/image/overlay2/layerdb/sha256/e9e6b8bf5c8da3818651580ac99dd83c56ba3e8569804209a766b30fc9a2d613/cache-id
138039e4cbcb0c99202a62a03e1b94f3070c39e5ae9bf5b0b09fe54c3d826893

#5.3 查看diff
> ls -l /var/lib/docker/overlay2/138039e4cbcb0c99202a62a03e1b94f3070c39e5ae9bf5b0b09fe54c3d826893/diff/
总用量 0
drwxr-xr-x 2 root root 28 3月   6 03:23 opt
drwx------ 2 root root 26 3月   6 03:23 root

#5.4 
> ls -l /var/lib/docker/overlay2/138039e4cbcb0c99202a62a03e1b94f3070c39e5ae9bf5b0b09fe54c3d826893/diff/opt/
总用量 4
-rw-r--r-- 1 root root 32 3月   6 06:10 layer_demo.txt

#5.5
cat /var/lib/docker/overlay2/138039e4cbcb0c99202a62a03e1b94f3070c39e5ae9bf5b0b09fe54c3d826893/diff/opt/layer_demo.txt
add new layer 1
add new layer 2

diffID

chainID[n] = sha256sum(chainID[n-1] diffID)

layerId
/var/lib/docker/image/overlay2/layerdb/sha256/${chainID}/cache-id
diff
sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa06284fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78ls -l /var/lib/docker/overlay2/ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78/diff/
总用量 12
drwxr-xr-x  2 root root 4096 4月   4 2022 bin
drwxr-xr-x  2 root root    6 4月   4 2022 dev
drwxr-xr-x 16 root root 4096 4月   4 2022 etc
drwxr-xr-x  2 root root    6 4月   4 2022 home
drwxr-xr-x  7 root root  247 4月   4 2022 lib
drwxr-xr-x  5 root root   44 4月   4 2022 media
drwxr-xr-x  2 root root    6 4月   4 2022 mnt
drwxr-xr-x  2 root root    6 4月   4 2022 opt
dr-xr-xr-x  2 root root    6 4月   4 2022 proc
drwx------  2 root root    6 4月   4 2022 root
drwxr-xr-x  2 root root    6 4月   4 2022 run
drwxr-xr-x  2 root root 4096 4月   4 2022 sbin
drwxr-xr-x  2 root root    6 4月   4 2022 srv
drwxr-xr-x  2 root root    6 4月   4 2022 sys
drwxrwxrwt  2 root root    6 4月   4 2022 tmp
drwxr-xr-x  7 root root   66 4月   4 2022 usr
drwxr-xr-x 12 root root  137 4月   4 2022 var
sha256:e912ed62f30d74714890b9c9effefe2ac53a9a3af3728b0dadb538b7ab03df770214ea74c08d5c79126342265ab19e9f466ed1b9c6dcf370e3a3b3f6d2e9c42a
sha256:a6e688425ad885c2a4f39ebdd5fc30ad41042fb2409d7184aa296abc88a160d2e9e6b8bf5c8da3818651580ac99dd83c56ba3e8569804209a766b30fc9a2d613

Docker容器使用overlayFS

        为了简单,用2层layer的Image讲解。alpine:3.15-layer1

# 1. 启动容器
> docker run -d --name container_layer_1 alpine:3.15-layer sleep infinity
2efc5c975fa584c24f5f86d42f0b5710983b0c41cd9bfea883656f94c5478472

# 2. 查看容器的mount情况
> docker inspect 2efc5c9
{
...
    "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/0afa0f6117293c388a34b845127513b9ca8e3b30aba5bc5b23715d44f355660a-init/diff:/var/lib/docker/overlay2/255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f/diff:/var/lib/docker/overlay2/ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78/diff",
                "MergedDir": "/var/lib/docker/overlay2/0afa0f6117293c388a34b845127513b9ca8e3b30aba5bc5b23715d44f355660a/merged",
                "UpperDir": "/var/lib/docker/overlay2/0afa0f6117293c388a34b845127513b9ca8e3b30aba5bc5b23715d44f355660a/diff",
                "WorkDir": "/var/lib/docker/overlay2/0afa0f6117293c388a34b845127513b9ca8e3b30aba5bc5b23715d44f355660a/work"
            },
            "Name": "overlay2"
        }
...
}

#3. 对应LowerDir,就是只读层,
# ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78 --> alpine最底层
# 255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f --> 我们构建的那一层

#4. 对应UpperDir,就是容器最上层,可写层
# 0afa0f6117293c388a34b845127513b9ca8e3b30aba5bc5b23715d44f355660a --> 可写层

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值