docker 镜像管理

docker本地镜像仓库的管理

启动一个容器需要镜像,根据Dockerfile构建镜像也会下载依赖的镜像,当使用docker pull拉取了外部镜像仓库的镜像时,docker是如何管理本地镜像的数据呢?

我的虚机中docker镜像存储驱动使用的是overlay,/var/lib/docker/image/overlay2/repositories.json,这个文件是一个简单的json文件,数据格式也非常简单,Repositories下面就依次列出了本地已经存在的所有镜像。

merge目录就是经过overlay2挂载以后,容器看到的rootfs的目录结构。

root@iZt4n1u8u50jg1r5n6myn2Z:~# cat /var/lib/docker/image/overlay2/repositories.json | jq
{
  "Repositories": {
    "alpine": {
      "alpine:3.11": "sha256:a787cb9865032e5b5a407ecdf34b57a23a4a076aaa043d71742ddb6726ec9229",
      "alpine@sha256:bcae378eacedab83da66079d9366c8f5df542d7ed9ab23bf487e3e1a8481375d": "sha256:a787cb9865032e5b5a407ecdf34b57a23a4a076aaa043d71742ddb6726ec9229"
    },
    "bitnami/php-fpm": {
      "bitnami/php-fpm:latest": "sha256:0d94e6597148af2af2cd8b894256ba21c6acb437f72518f7ce251a3ea85421d3",
      "bitnami/php-fpm@sha256:dba2bb41c613c825d2e7fa88fdcd2ec662f90e1c026615c05789a1ed34a17d99": "sha256:0d94e6597148af2af2cd8b894256ba21c6acb437f72518f7ce251a3ea85421d3"
    },
    "busybox": {
      "busybox:latest": "sha256:d23834f29b3875b6759be00a48013ba523c6a89fcbaeaa63607512118a9c4c19",
      "busybox@sha256:52817dece4cfe26f581c834d27a8e1bcc82194f914afe6d50afad5a101234ef1": "sha256:d23834f29b3875b6759be00a48013ba523c6a89fcbaeaa63607512118a9c4c19"
    },
    "calico-node": {
      "calico-node:base": "sha256:80a1a6b0a19c0d01d79fbb10ad9c17dd901106fa085958fbb75fcbf8873f08c4"
    },
    "calico/bird": {
      "calico/bird:v0.3.3-182-g4b493986-amd64": "sha256:039b1de045060e8dad02608cc29ba9e1b144bd364fe3521dca5ce98bb2aaef47",
      "calico/bird@sha256:f040de1b528e3a7fd59a7c81aa9ca6096cc4ac2564337c2ff3d52dbdf07ca9be": "sha256:039b1de045060e8dad02608cc29ba9e1b144bd364fe3521dca5ce98bb2aaef47"
    },
    "calico/bpftool": {
      "calico/bpftool:v5.3-amd64": "sha256:bc0875ac43440ae8d7361f76d83472e3000231885866c46d2f0d7cb36c9a8368",
      "calico/bpftool@sha256:2903c00eef4431140adc4655b10f5645dc1f9cc78c8a20d04682356670a02ba5": "sha256:bc0875ac43440ae8d7361f76d83472e3000231885866c46d2f0d7cb36c9a8368"
    },
}

查看镜像的manifest信息

使用docker manifest inspect可以查看镜像的manifest信息,manifest描述了关于镜像存储的一些信息,mediaType表示配置描述的类型。

  • config中的mediaType为container.image.v1+json,这个就表示存储镜像的配置信息是一个json类型的文件,sha256中的数字就是镜像的配置文件的id,docker inspect这个id或者使用cat命令输出该文件的内容,这两个是一致的。
  • 下面的layers中的mediaType为image.rootfs.diff.tar.gzip,就表示这是镜像中的一层数据,存储格式为tar包。
root@iZt4n1u8u50jg1r5n6myn2Z:~# docker manifest inspect goharbor/harbor-db-base:dev
{
        "schemaVersion": 2,
        "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
        "config": {
                "mediaType": "application/vnd.docker.container.image.v1+json",
                "size": 4111,
                "digest": "sha256:2ed2ba057d8cabed044c54d36f918ea16673e3a289fa89c7520f57d46d7b3bfd"
        },
        "layers": [
                {
                        "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                        "size": 15994577,
                        "digest": "sha256:cb54d1184a86b82843c849bbd232f27fd0b1b012c8770baea97b5a05244b2f48"
                },
                {
                        "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                        "size": 1080392,
                        "digest": "sha256:7463ba7e68d03f78269f3f2ae4f6b15cc45d72d6c15989cf0cbdfe8dd625c2d0"
                },
                {
                        "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                        "size": 5665629,
                        "digest": "sha256:ba06e5eb0d9c49f23d81fa2cdcc91f792ecf3a0c27710bdcf5622cef940897bc"
                },
                {
                        "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                        "size": 62049341,
                        "digest": "sha256:604a291316d51f6a760b233cb6ce9680cc36cbe464933ff258c7a1bffd9c80af"
                },
                {
                        "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                        "size": 12733349,
                        "digest": "sha256:e12f21e5718e13baf221587a559b1700dee8957cb39e9ef8906846c0195535a3"
                }
        ]
}

查看镜像的详细配置信息

使用docker inspect命令查看一个镜像的详细配置信息。

root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# docker inspect google/cadvisor:v0.33.0
[
    {
        "Id": "sha256:752d61707eac173cfe56a23aa9de051597444286163667d60f8e6d4c63306472",
        "RepoTags": [
            "google/cadvisor:v0.33.0"
        ],
        "RepoDigests": [
            "google/cadvisor@sha256:47f1f8c02a3acfab77e74e2ec7acc0d475adc180ddff428503a4ce63f3d6061b"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2019-02-27T18:40:08.005242894Z",
        "Container": "60b721dff23e41eee7d1728fdf0d62deff5c0ee053e29ba5da556b8b4fae93fa",
        "ContainerConfig": {
            "Hostname": "60b721dff23e",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "8080/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "GLIBC_VERSION=2.28-r0"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "ENTRYPOINT [\"/usr/bin/cadvisor\" \"-logtostderr\"]"
            ],
            "Healthcheck": {
                "Test": [
                    "CMD-SHELL",
                    "curl -f http://localhost:8080/healthz || exit 1"
                ],
                "Interval": 30000000000,
                "Timeout": 3000000000
            },
            "ArgsEscaped": true,
            "Image": "sha256:338328de3ca3663d600e94c0a2b3aee1df611f293c858b63d2fa9fa44bd53329",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "/usr/bin/cadvisor",
                "-logtostderr"
            ],
            "OnBuild": null,
            "Labels": {}
        },
        "DockerVersion": "18.06.2-ce",
        "Author": "dengnan@google.com vmarmol@google.com vishnuk@google.com jimmidyson@gmail.com stclair@google.com",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "8080/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "GLIBC_VERSION=2.28-r0"
            ],
            "Cmd": null,
            "Healthcheck": {
                "Test": [
                    "CMD-SHELL",
                    "curl -f http://localhost:8080/healthz || exit 1"
                ],
                "Interval": 30000000000,
                "Timeout": 3000000000
            },
            "ArgsEscaped": true,
            "Image": "sha256:338328de3ca3663d600e94c0a2b3aee1df611f293c858b63d2fa9fa44bd53329",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "/usr/bin/cadvisor",
                "-logtostderr"
            ],
            "OnBuild": null,
            "Labels": null
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 68607708,
        "VirtualSize": 68607708,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/1fc34ade9326a48261bfb2f5e3b134cc1db5b9e2f1faf7d5df5049be05d1fbd1/diff:/var/lib/docker/overlay2/5b1f40c8ed48fd43aa47d947d84eda7b80ca866aeb49c485dda326ca8eb76f76/diff",
                "MergedDir": "/var/lib/docker/overlay2/8f377f94a7e3ab7c609e4054b414d346416a1f62a3ad9098ff7c0510a82212e9/merged",
                "UpperDir": "/var/lib/docker/overlay2/8f377f94a7e3ab7c609e4054b414d346416a1f62a3ad9098ff7c0510a82212e9/diff",
                "WorkDir": "/var/lib/docker/overlay2/8f377f94a7e3ab7c609e4054b414d346416a1f62a3ad9098ff7c0510a82212e9/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:767f936afb51c8a3ad9a96592a4be092048bb70f2ca410028a0b3f64b826acbb",
                "sha256:6a395a55089d2d886fdc814cf412e20d9d279110a3eb5768550b01f61e7b9cdb",
                "sha256:09c65671850474d73700a2943d1564b60036dcc84122f8ffcd6cb34a2d2f9479"
            ]
        },
    }
]

Layers中有三个sha256的数字,表示这个镜像有三层组成,最上面是最底层的,最下面是最上层的。

1、sha256:767f936afb51c8a3ad9a96592a4be092048bb70f2ca410028a0b3f64b826acbb
2、sha256:6a395a55089d2d886fdc814cf412e20d9d279110a3eb5768550b01f61e7b9cdb
3、sha256:09c65671850474d73700a2943d1564b60036dcc84122f8ffcd6cb34a2d2f9479

查找第一层的数据

root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# find -name "767f936afb51c8a3ad9a96592a4be092048bb70f2ca410028a0b3f64b826acbb"
./image/overlay2/layerdb/sha256/767f936afb51c8a3ad9a96592a4be092048bb70f2ca410028a0b3f64b826acbb
./image/overlay2/distribution/v2metadata-by-diffid/sha256/767f936afb51c8a3ad9a96592a4be092048bb70f2ca410028a0b3f64b826acbb
root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker#

按照公式查找第二层

root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# echo -n "sha256:767f936afb51c8a3ad9a96592a4be092048bb70f2ca410028a0b3f64b826acbb sha256:6a395a55089d2d886fdc814cf412e20d9d279110a3eb5768550b01f61e7b9cdb" | sha256sum 
57cbd50652751eebe058602a11d336fca0819d6394a11d032c6260fd3e811d2e  -

#确认层次
root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# cat ./image/overlay2/layerdb/sha256/57cbd50652751eebe058602a11d336fca0819d6394a11d032c6260fd3e811d2e/parent 
sha256:767f936afb51c8a3ad9a96592a4be092048bb70f2ca410028a0b3f64b826acbb

按照公式查找第三层,chainID=sha256sum(H(chainID) diffid)

root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# echo -n "sha256:57cbd50652751eebe058602a11d336fca0819d6394a11d032c6260fd3e811d2e sha256:09c65671850474d73700a2943d1564b60036dcc84122f8ffcd6cb34a2d2f9479" | sha256sum 
bdb7cdf8feed1bb5298e86ea62b251f6e22f505f13238c3a06e33a50313c38cd  -
root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# find -name "bdb7cdf8feed1bb5298e86ea62b251f6e22f505f13238c3a06e33a50313c38cd"
./image/overlay2/layerdb/sha256/bdb7cdf8feed1bb5298e86ea62b251f6e22f505f13238c3a06e33a50313c38cd

#确认
root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# cat ./image/overlay2/layerdb/sha256/bdb7cdf8feed1bb5298e86ea62b251f6e22f505f13238c3a06e33a50313c38cd/parent 
sha256:57cbd50652751eebe058602a11d336fca0819d6394a11d032c6260fd3e811d2e

根据上面计算出来的chains,查看目录下的cache-id,查看对应的目录

# 计算出来的三层
1、767f936afb51c8a3ad9a96592a4be092048bb70f2ca410028a0b3f64b826acbb
2、57cbd50652751eebe058602a11d336fca0819d6394a11d032c6260fd3e811d2e
3、bdb7cdf8feed1bb5298e86ea62b251f6e22f505f13238c3a06e33a50313c38cd

# 查看第一层数据目录
cat image/overlay2/layerdb/sha256/767f936afb51c8a3ad9a96592a4be092048bb70f2ca410028a0b3f64b826acbb/cache-id
5b1f40c8ed48fd43aa47d947d84eda7b80ca866aeb49c485dda326ca8eb76f76

root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# ls overlay2/5b1f40c8ed48fd43aa47d947d84eda7b80ca866aeb49c485dda326ca8eb76f76/diff/
bin  dev  etc  home  lib  media  mnt  proc  root  run  sbin  srv  sys  tmp  usr  var
# 查看第二层的数据
root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# cat image/overlay2/layerdb/sha256/57cbd50652751eebe058602a11d336fca0819d6394a11d032c6260fd3e811d2e/cache-id 
1fc34ade9326a48261bfb2f5e3b134cc1db5b9e2f1faf7d5df5049be05d1fbd1

root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# ls  overlay2/1fc34ade9326a48261bfb2f5e3b134cc1db5b9e2f1faf7d5df5049be05d1fbd1/diff/
etc  lib  lib64  sbin  usr  var

# 查看第三层的数据
root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# cat image/overlay2/layerdb/sha256/bdb7cdf8feed1bb5298e86ea62b251f6e22f505f13238c3a06e33a50313c38cd/cache-id 
8f377f94a7e3ab7c609e4054b414d346416a1f62a3ad9098ff7c0510a82212e9

root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# ls overlay2/8f377f94a7e3ab7c609e4054b414d346416a1f62a3ad9098ff7c0510a82212e9/diff/
usr

启动一个容器

root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# docker run --entrypoint sh --rm -it google/cadvisor:v0.33.0 
/ # ls
bin    dev    etc    home   lib    lib64  media  mnt    proc   root   run    sbin   srv    sys    tmp    usr    var

查看容器id

root@iZt4n1u8u50jg1r5n6myn2Z:~# docker ps 
CONTAINER ID   IMAGE                           COMMAND                  CREATED          STATUS                             PORTS                                                                                  NAMES
072afc5171ff   google/cadvisor:v0.33.0         "sh"                     13 seconds ago   Up 12 seconds (health: starting)   8080/tcp                                                                               goofy_colden 

查看容器的相关信息

root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# find -name "072afc5171ff*"
./containers/072afc5171fff6aceaf669c7ecb6df9902129f912512c7f8bfe5aac7dad748c0
./containers/072afc5171fff6aceaf669c7ecb6df9902129f912512c7f8bfe5aac7dad748c0/072afc5171fff6aceaf669c7ecb6df9902129f912512c7f8bfe5aac7dad748c0-json.log
./image/overlay2/layerdb/mounts/072afc5171fff6aceaf669c7ecb6df9902129f912512c7f8bfe5aac7dad748c0
root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# 

image/overlay2/layerdb/mounts目录下有个以容器id命名的目录,有一个init-id后缀的文件,从名称上看应该是容器的一些特性化数据,做一个形象的解释是,一个进程在容器中运行,虽然被限制了很多,但是该有的配套设施还是要有的。如在docker run中添加的dns信息就会存储在这个init-id目录下的etc/resolve.conf。

# init-id和mount-id是一样的,是本层的id
# parent的id是最上面的一层。
root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# cat ./image/overlay2/layerdb/mounts/072afc5171fff6aceaf669c7ecb6df9902129f912512c7f8bfe5aac7dad748c0/init-id 
a7a9309e6d612f56f02aa88df32c3366f1ac65c27ca523f85b628569cc19b300-init
root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# 
root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker#  cat ./image/overlay2/layerdb/mounts/072afc5171fff6aceaf669c7ecb6df9902129f912512c7f8bfe5aac7dad748c0/mount-id 
a7a9309e6d612f56f02aa88df32c3366f1ac65c27ca523f85b628569cc19b300
root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# 
root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# cat ./image/overlay2/layerdb/mounts/072afc5171fff6aceaf669c7ecb6df9902129f912512c7f8bfe5aac7dad748c0/parent 
sha256:bdb7cdf8feed1bb5298e86ea62b251f6e22f505f13238c3a06e33a50313c38cd

root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# ls  ./overlay2/a7a9309e6d612f56f02aa88df32c3366f1ac65c27ca523f85b628569cc19b300-init/diff/
dev  etc

root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# ls overlay2/a7a9309e6d612f56f02aa88df32c3366f1ac65c27ca523f85b628569cc19b300/
diff  link  lower  merged  work
root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# ls overlay2/a7a9309e6d612f56f02aa88df32c3366f1ac65c27ca523f85b628569cc19b300/diff/
root
root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# ls overlay2/a7a9309e6d612f56f02aa88df32c3366f1ac65c27ca523f85b628569cc19b300/merged/
bin  dev  etc  home  lib  lib64  media  mnt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@iZt4n1u8u50jg1r5n6myn2Z:/var/lib/docker# 

下篇预告

容器启动后看到的目录只有一个,这个目录又是多个目录联合形成的,那么容器访问一个rootfs文件的流程又是怎样的呢?下篇将会深入介绍overlayfs文件系统的原理,敬请期待。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 223,507评论 6 521
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 95,626评论 3 401
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 170,466评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,456评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,473评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,016评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,409评论 3 426
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,370评论 0 278
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,909评论 1 322
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,960评论 3 343
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,102评论 1 354
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,754评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,428评论 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,917评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,036评论 1 275
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,582评论 3 380
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,126评论 2 362

推荐阅读更多精彩内容