目录

前言

镜像本地存储分析

新增文件测试构建test镜像

新增文件测试构建test2镜像

镜像Tar包存储分析

总结

参考


前言

首先镜像有如下四个保存形式

1.远程镜像仓库保存

2.本地保存

2.1 镜像时保存方式

2.2 容器运行时保存方式

3.tar包

在这里我们仅仅讨论,本地保存方式,既docker pull后保存和docker run后运行存储是什么样的,下面的案例是docker run后的

首先我们需要使用命令docker info来查看存放目录,再看存储驱动

┌──(root💀kali)-[/home/kali/Desktop]
└─# docker info | grep 'Docker Root Dir'                                                                                                        
 Docker Root Dir: /var/lib/docker
┌──(root💀kali)-[/home/kali/Desktop]
└─# docker info | grep Storage
 Storage Driver: overlay2

可以看到,显示Docker root dir为/var/lib/docker目录,也就是数据会被保存在该目录下,但是我们以何种形式保存,取决于我们的graphdriver,下列我们以overlayfs来讨论。

我们使用docker inspect 镜像名 -> GraphDriver -> MergeDir标签,即可找到我们的镜像保存位置,其运用了联合挂载原理。

下面我们以为ubuntu镜像来分析

镜像本地存储分析

执行下列命令

docker inspect ubuntu:latest

内容如下


    {
        "Id": "sha256:e343402cadef796b4f12c2ee20b7346978a42a8d95516619c36c6397c4b0c766",
        "RepoTags": [
            "ubuntu:latest"
        ],
        "RepoDigests": [
            "ubuntu@sha256:2b7412e6465c3c7fc5bb21d3e6f1917c167358449fecac8176c6e496e5c1f05f"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2023-10-05T07:32:22.848629339Z",
        "Container": "101bef02c4ca8881845263dfcff12029b02cb88b609c74964ec32ee8b87c79ed",
        "ContainerConfig": {
            "Hostname": "101bef02c4ca",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"/bin/bash\"]"
            ],
            "Image": "sha256:c23ecf8cd0797332c93851bd9f66e571a65fa281fcb83507473688be2000d54c",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.opencontainers.image.ref.name": "ubuntu",
                "org.opencontainers.image.version": "22.04"
            }
        },
        "DockerVersion": "20.10.21",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "Image": "sha256:c23ecf8cd0797332c93851bd9f66e571a65fa281fcb83507473688be2000d54c",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.opencontainers.image.ref.name": "ubuntu",
                "org.opencontainers.image.version": "22.04"
            }
        },
        "Architecture": "arm64",
        "Variant": "v8",
        "Os": "linux",
        "Size": 69192530,
        "VirtualSize": 69192530,
        "GraphDriver": {
            "Data": {
                "MergedDir": "/var/lib/docker/overlay2/f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28/merged",
                "UpperDir": "/var/lib/docker/overlay2/f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28/diff",
                "WorkDir": "/var/lib/docker/overlay2/f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:d2d3127fc3d362a0516c53fcb8fb983ebb9d1ea2dfbd63b69967a0084f0d45a3"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

依次访问GraphDriver下,我们可以看到是可以进入到diff文件目录查看到ubuntu下的所有文件

root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/diff# cd /var/lib/docker/overlay2/f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28/diff
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28/diff# ls
bin  boot  dev  etc  home  lib  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28/diff# cd /var/lib/docker/overlay2/f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28/work
bash: cd: /var/lib/docker/overlay2/f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28/work: No such file or directory

新增文件测试构建test镜像

当我们新增文件后,我们可以看到,lowerDir为f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28

[
    {
        "Id": "sha256:e609c21b5859269bf25ac73d536852cfb22b6350c9d96df67e4821b9dbc96029",
        "RepoTags": [
            "test:latest"
        ],
        "RepoDigests": [],
        "Parent": "sha256:f520d5de01c8ed34a2e3d005a56f0e2b18342d384c8b5c574ce7c38704ceb1a0",
        "Comment": "",
        "Created": "2023-10-30T07:02:58.496229265Z",
        "Container": "a717a938ebc0c1fce5a293c447a40af1ad5e6406176e598e96a65ca6056ab17f",
        "ContainerConfig": {
            "Hostname": "a717a938ebc0",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "ENTRYPOINT [\"tail\" \"-f\" \"/dev/null\"]"
            ],
            "Image": "sha256:f520d5de01c8ed34a2e3d005a56f0e2b18342d384c8b5c574ce7c38704ceb1a0",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "tail",
                "-f",
                "/dev/null"
            ],
            "OnBuild": null,
            "Labels": {
                "org.opencontainers.image.ref.name": "ubuntu",
                "org.opencontainers.image.version": "22.04"
            }
        },
        "DockerVersion": "24.0.5",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": null,
            "Image": "sha256:f520d5de01c8ed34a2e3d005a56f0e2b18342d384c8b5c574ce7c38704ceb1a0",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "tail",
                "-f",
                "/dev/null"
            ],
            "OnBuild": null,
            "Labels": {
                "org.opencontainers.image.ref.name": "ubuntu",
                "org.opencontainers.image.version": "22.04"
            }
        },
        "Architecture": "arm64",
        "Variant": "v8",
        "Os": "linux",
        "Size": 69192535,
        "VirtualSize": 69192535,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28/diff",
                "MergedDir": "/var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/merged",
                "UpperDir": "/var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/diff",
                "WorkDir": "/var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:d2d3127fc3d362a0516c53fcb8fb983ebb9d1ea2dfbd63b69967a0084f0d45a3",
                "sha256:20de5a421c44c4c61291881fe9f0e06024c4e6b90c695c6c6f0543a4a196866e"
            ]
        },
        "Metadata": {
            "LastTagTime": "2023-10-30T15:03:00.472084414+08:00"
        }
    }
]

分别进入GraphDriver查看

root@ubuntu-linux-22-04-desktop:/# cd /var/lib/docker/overlay2/f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28/diff

root@ubuntu-linux-22-04-desktop:/# ls
bin  boot  dev  etc  home  lib  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

root@ubuntu-linux-22-04-desktop:/# cd /var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/merged
bash: cd: /var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/merged: No such file or directory

root@ubuntu-linux-22-04-desktop:/# cd /var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/diff
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/diff# ls
home
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/diff# cd home
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/diff/home# cat test.txt 
test
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/diff/home# ls
test.txt
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/diff/home# cd /var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/work
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/work# ls
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/work# 

也就是从上面可以得知,我们的lowerdir是ubuntu镜像保存在/var/lib/docker/overlay2下的目录作为lowerdir路径,Docker是分层以来,也能说明,该镜像依赖于ubuntu。接下来我们继续提交新的文件,将test2.txt加入到镜像中,新建如下Dockerfile2

FROM test:latest
COPY ./test2.txt /home
ENTRYPOINT ["tail", "-f", "/dev/null"]

使用该命令来基于test镜像构建test2镜像

docker build -t test2 -f Dockerfile2 .

新增文件测试构建test2镜像

构建完成的test2镜像通过docker inspect查询到的内容如下所示


    {
        "Id": "sha256:6e94e9b361cb45f9ba7dcd932782b503a90b5ecfb14443c5a081f36f188c731e",
        "RepoTags": [
            "test2:latest"
        ],
        "RepoDigests": [],
        "Parent": "sha256:75c07bad05e3e5b85f45fc11f1deac5fea4e773c5ec440b6ace7245fda738da0",
        "Comment": "",
        "Created": "2023-10-30T08:19:29.029483613Z",
        "Container": "3a5896e2f0440d1c3506733ad8155c8b142d0d3e8b56152528d553116252d4dc",
        "ContainerConfig": {
            "Hostname": "3a5896e2f044",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "ENTRYPOINT [\"tail\" \"-f\" \"/dev/null\"]"
            ],
            "Image": "sha256:75c07bad05e3e5b85f45fc11f1deac5fea4e773c5ec440b6ace7245fda738da0",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "tail",
                "-f",
                "/dev/null"
            ],
            "OnBuild": null,
            "Labels": {
                "org.opencontainers.image.ref.name": "ubuntu",
                "org.opencontainers.image.version": "22.04"
            }
        },
        "DockerVersion": "24.0.5",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": null,
            "Image": "sha256:75c07bad05e3e5b85f45fc11f1deac5fea4e773c5ec440b6ace7245fda738da0",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "tail",
                "-f",
                "/dev/null"
            ],
            "OnBuild": null,
            "Labels": {
                "org.opencontainers.image.ref.name": "ubuntu",
                "org.opencontainers.image.version": "22.04"
            }
        },
        "Architecture": "arm64",
        "Variant": "v8",
        "Os": "linux",
        "Size": 69192540,
        "VirtualSize": 69192540,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/58c1840142e7115c9dc717173fec20ac44ba0cc8e7e1430227720bb197c75e51/diff:/var/lib/docker/overlay2/f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28/diff",
                "MergedDir": "/var/lib/docker/overlay2/425b247368c0c8a92e62afcdf18512270834e12d7f2562aa213679c3f6c15364/merged",
                "UpperDir": "/var/lib/docker/overlay2/425b247368c0c8a92e62afcdf18512270834e12d7f2562aa213679c3f6c15364/diff",
                "WorkDir": "/var/lib/docker/overlay2/425b247368c0c8a92e62afcdf18512270834e12d7f2562aa213679c3f6c15364/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:d2d3127fc3d362a0516c53fcb8fb983ebb9d1ea2dfbd63b69967a0084f0d45a3",
                "sha256:20de5a421c44c4c61291881fe9f0e06024c4e6b90c695c6c6f0543a4a196866e",
                "sha256:6ae03509a28ebad8c9d6057911ca488e753b60550fd1354ed3c2ab5cff3bffdf"
            ]
        },
        "Metadata": {
            "LastTagTime": "2023-10-30T16:19:29.042331284+08:00"
        }
    }
]

可以看到lowerDir新增了一个目录,也就是上面打包的test目录,也就是说,又新增了一个依赖层,然后我们新增的文件,又添加到了diff文件夹,执行目录遍历过程如下所示

root@ubuntu-linux-22-04-desktop:/# cd /var/lib/docker/overlay2/425b247368c0c8a92e62afcdf18512270834e12d7f2562aa213679c3f6c15364/merged
bash: cd: /var/lib/docker/overlay2/425b247368c0c8a92e62afcdf18512270834e12d7f2562aa213679c3f6c15364/merged: No such file or directory
root@ubuntu-linux-22-04-desktop:/# cd /var/lib/docker/overlay2/425b247368c0c8a92e62afcdf18512270834e12d7f2562aa213679c3f6c15364/diff
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/425b247368c0c8a92e62afcdf18512270834e12d7f2562aa213679c3f6c15364/diff# ls
home
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/425b247368c0c8a92e62afcdf18512270834e12d7f2562aa213679c3f6c15364/diff# cd home/
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/425b247368c0c8a92e62afcdf18512270834e12d7f2562aa213679c3f6c15364/diff/home# ls
test2.txt
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/425b247368c0c8a92e62afcdf18512270834e12d7f2562aa213679c3f6c15364/diff/home# cat test2.txt 
test
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/425b247368c0c8a92e62afcdf18512270834e12d7f2562aa213679c3f6c15364/diff/home# cd /var/lib/docker/overlay2/425b247368c0c8a92e62afcdf18512270834e12d7f2562aa213679c3f6c15364/work
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/425b247368c0c8a92e62afcdf18512270834e12d7f2562aa213679c3f6c15364/work#

镜像Tar包存储分析

镜像tar存储如下

manifest.json

[{"Config":"e343402cadef796b4f12c2ee20b7346978a42a8d95516619c36c6397c4b0c766.json","RepoTags":null,"Layers":["b043fd2c620c3d3d98f640c0a3d4f45595e797180ebcae7e76922a85031e3f29/layer.tar"]}]

e343402cadef796b4f12c2ee20b....json

[{"Config":"e343402cadef796b4f12c2ee20b7346978a42a8d95516619c36c6397c4b0c766.json","RepoTags":null,"Layers":["b043fd2c620c3d3d98f640c0a3d4f45595e797180ebcae7e76922a85031e3f29/layer.tar"]}]

进入b043f后如下所示

json

{"id":"b043fd2c620c3d3d98f640c0a3d4f45595e797180ebcae7e76922a85031e3f29","created":"2023-10-05T07:32:22.848629339Z","container":"101bef02c4ca8881845263dfcff12029b02cb88b609c74964ec32ee8b87c79ed","container_config":{"Hostname":"101bef02c4ca","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh","-c","#(nop) ","CMD [\"/bin/bash\"]"],"Image":"sha256:c23ecf8cd0797332c93851bd9f66e571a65fa281fcb83507473688be2000d54c","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":{"org.opencontainers.image.ref.name":"ubuntu","org.opencontainers.image.version":"22.04"}},"docker_version":"20.10.21","config":{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/bash"],"Image":"sha256:c23ecf8cd0797332c93851bd9f66e571a65fa281fcb83507473688be2000d54c","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":{"org.opencontainers.image.ref.name":"ubuntu","org.opencontainers.image.version":"22.04"}},"architecture":"arm64","variant":"v8","os":"linux"}

layer.tar

运行时镜像存储分析

首先我们来运行最基础的ubuntu:latest镜像来看下运行状态,通过命令

docker run -itd ubuntu:latest

来运行,之后通过下列命令,获取运行时容器内容如下所示

[
    {
        "Id": "b0f3abec3b5e3c6194bcef0857f5aa8af658cc13b153475249a9c73c84d55215",
        "Created": "2023-10-30T09:05:12.38240903Z",
        "Path": "/bin/bash",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 135490,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2023-10-30T09:05:12.564128307Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:e343402cadef796b4f12c2ee20b7346978a42a8d95516619c36c6397c4b0c766",
        "ResolvConfPath": "/var/lib/docker/containers/b0f3abec3b5e3c6194bcef0857f5aa8af658cc13b153475249a9c73c84d55215/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/b0f3abec3b5e3c6194bcef0857f5aa8af658cc13b153475249a9c73c84d55215/hostname",
        "HostsPath": "/var/lib/docker/containers/b0f3abec3b5e3c6194bcef0857f5aa8af658cc13b153475249a9c73c84d55215/hosts",
        "LogPath": "/var/lib/docker/containers/b0f3abec3b5e3c6194bcef0857f5aa8af658cc13b153475249a9c73c84d55215/b0f3abec3b5e3c6194bcef0857f5aa8af658cc13b153475249a9c73c84d55215-json.log",
        "Name": "/pedantic_tu",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "docker-default",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {},
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "ConsoleSize": [
                36,
                151
            ],
            "CapAdd": null,
            "CapDrop": null,
            "CgroupnsMode": "private",
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": [],
            "BlkioDeviceWriteBps": [],
            "BlkioDeviceReadIOps": [],
            "BlkioDeviceWriteIOps": [],
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": null,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/a0ba26d7e82a6724381fa633c643596261ccc6a982d14f3464a0c415bf4f8293-init/diff:/var/lib/docker/overlay2/f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28/diff",
                "MergedDir": "/var/lib/docker/overlay2/a0ba26d7e82a6724381fa633c643596261ccc6a982d14f3464a0c415bf4f8293/merged",
                "UpperDir": "/var/lib/docker/overlay2/a0ba26d7e82a6724381fa633c643596261ccc6a982d14f3464a0c415bf4f8293/diff",
                "WorkDir": "/var/lib/docker/overlay2/a0ba26d7e82a6724381fa633c643596261ccc6a982d14f3464a0c415bf4f8293/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "b0f3abec3b5e",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "Image": "ubuntu:latest",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.opencontainers.image.ref.name": "ubuntu",
                "org.opencontainers.image.version": "22.04"
            }
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "f607b1753aa37067fab841269dead95dd77d30342bce1dfeb481d20eafa0b5b9",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/f607b1753aa3",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "856aac0592dee67748febddef3f8779c0a454a505b940603cf8c042d7e412d0b",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.3",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:03",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "5d13fa06857575a1e7237e12b4e615e72a1f6402a32dec88e63066e7e088a31f",
                    "EndpointID": "856aac0592dee67748febddef3f8779c0a454a505b940603cf8c042d7e412d0b",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.3",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:03",
                    "DriverOpts": null
                }
            }
        }
    }
]

我们继续和之前一样,查看graphGriver,如下所示

"GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/a0ba26d7e82a6724381fa633c643596261ccc6a982d14f3464a0c415bf4f8293-init/diff:/var/lib/docker/overlay2/f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28/diff",
                "MergedDir": "/var/lib/docker/overlay2/a0ba26d7e82a6724381fa633c643596261ccc6a982d14f3464a0c415bf4f8293/merged",
                "UpperDir": "/var/lib/docker/overlay2/a0ba26d7e82a6724381fa633c643596261ccc6a982d14f3464a0c415bf4f8293/diff",
                "WorkDir": "/var/lib/docker/overlay2/a0ba26d7e82a6724381fa633c643596261ccc6a982d14f3464a0c415bf4f8293/work"
            },
            "Name": "overlay2"
        },

我们发现,对于镜像来说,多了一个init层,那么init层是干嘛的呢,本质上是由于lowerDir是镜像层,指向镜像存储的地方,不允许修改,而容器运时候用户会修改一些相关内容,例如host那么,就通过新增一个init层来完成这样的修改,并且和容器绑定,我们下面创建两个容器来看一下

docker run -itd ubuntu:latest后inpsect后的graphdriver如下
"GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/228c7d31fc94dcb1386e0319e207ac6c63affaffe63243b84e8ed9b2a097a9d9-init/diff:/var/lib/docker/overlay2/f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28/diff",
                "MergedDir": "/var/lib/docker/overlay2/228c7d31fc94dcb1386e0319e207ac6c63affaffe63243b84e8ed9b2a097a9d9/merged",
                "UpperDir": "/var/lib/docker/overlay2/228c7d31fc94dcb1386e0319e207ac6c63affaffe63243b84e8ed9b2a097a9d9/diff",
                "WorkDir": "/var/lib/docker/overlay2/228c7d31fc94dcb1386e0319e207ac6c63affaffe63243b84e8ed9b2a097a9d9/work"
            },
            "Name": "overlay2"
        },


第二次运行docker run -itd ubuntu:latest后inpsect后的graphdriver如下

"GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/d3de15b70c15e891d1d4c4bd254385ceb0e474a13d2bd781bc3517be99280e10-init/diff:/var/lib/docker/overlay2/f4de6d4539cacaf9c8bf28b5d74faaab19af680272b1e90aeb89fb251d5a3a28/diff",
                "MergedDir": "/var/lib/docker/overlay2/d3de15b70c15e891d1d4c4bd254385ceb0e474a13d2bd781bc3517be99280e10/merged",
                "UpperDir": "/var/lib/docker/overlay2/d3de15b70c15e891d1d4c4bd254385ceb0e474a13d2bd781bc3517be99280e10/diff",
                "WorkDir": "/var/lib/docker/overlay2/d3de15b70c15e891d1d4c4bd254385ceb0e474a13d2bd781bc3517be99280e10/work"
            },
            "Name": "overlay2"
        },

可以看到,每次运行一个容器,都会新开一个目录存放容器,并且lowerdir包括了init和依赖的镜像目录,具体内容如下

root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/a0ba26d7e82a6724381fa633c643596261ccc6a982d14f3464a0c415bf4f8293-init/diff# ls
dev  etc
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/a0ba26d7e82a6724381fa633c643596261ccc6a982d14f3464a0c415bf4f8293-init/diff# cd etc/
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/a0ba26d7e82a6724381fa633c643596261ccc6a982d14f3464a0c415bf4f8293-init/diff/etc# ls
hostname  hosts  mtab  resolv.conf
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/a0ba26d7e82a6724381fa633c643596261ccc6a982d14f3464a0c415bf4f8293-init/diff/etc# cat hosts
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/a0ba26d7e82a6724381fa633c643596261ccc6a982d14f3464a0c415bf4f8293-init/diff/etc# cat resolv.conf 
root@ubuntu-linux-22-04-desktop:/var/lib/docker/overlay2/a0ba26d7e82a6724381fa633c643596261ccc6a982d14f3464a0c415bf4f8293-init/diff/etc# cat hostname 

总结

对于运行时容器

docker inspect 运行时容器名 -> GraphDriver -> MergeDir

对于镜像

docker inspect 运行时容器名 -> GraphDriver -> lowerDir + Upperdir

如果是最基础的镜像则没有lowerDir,例如ubuntu

参考

手撕docker文件结构 —— overlayFS,image,container文件结构详解 - 知乎

docker 镜像与容器存储目录结构精讲-阿里云开发者社区

Docker容器镜像仓库存储原理(前世今身)与搬运技巧-腾讯云开发者社区-腾讯云

docker 镜像存储分析 - 简书

Use the OverlayFS storage driver | Docker Docs

https://www.freecodecamp.org/news/where-are-docker-images-stored-docker-container-paths-explained/

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐