Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@x-yuri
Last active December 28, 2022 10:33
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save x-yuri/c4eb4a900ee2f10e2568c96bacf0f9fd to your computer and use it in GitHub Desktop.
Save x-yuri/c4eb4a900ee2f10e2568c96bacf0f9fd to your computer and use it in GitHub Desktop.
Examining images and docker registry #docker #registry #images

Examining images and docker registry

Dockerfile:

FROM alpine
RUN echo a > a
COPY b .

b:

b

Build the image:

$ docker build -t registry.com/test-img:v1 .

Inspect the image:

$ docker images registry.com/test-img:v1 --format '{{.ID}}'
cfc17f8cb22d

$ docker inspect cfc17f8cb22d
[
    {
        "Id": "sha256:cfc17f8cb22d6e17b9a2e88bd1d6c7f9cf5a0fda6bc788e77e3f7ad1d3fdae26",
        "RepoTags": [
            "registry.com/test-img:v1"
        ],
        "RepoDigests": [
            "registry.com/test-img@sha256:1ed6da69b82018bee5dfc0ac48b24890cd10044072058e9d97a6327d50be2f73"
        ],
        "Parent": "sha256:79ed4e0c3a63b88f51629582d60429403d78def523821a18b7adc3bd4fe687f3",
        "Comment": "",
        "Created": "2021-12-02T08:40:40.000939697Z",
        "Container": "",
        "ContainerConfig": {
            "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/sh",
                "-c",
                "#(nop) COPY file:c30af0dc159ad65333707b5f57d479de06c1a4bae1566e1dc8e71e8446d68b4d in . "
            ],
            "Image": "sha256:79ed4e0c3a63b88f51629582d60429403d78def523821a18b7adc3bd4fe687f3",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": null
        },
        "DockerVersion": "20.10.10",
        "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/sh"
            ],
            "Image": "sha256:79ed4e0c3a63b88f51629582d60429403d78def523821a18b7adc3bd4fe687f3",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": null
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 5590946,
        "VirtualSize": 5590946,
        "GraphDriver": {...},
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:bc276c40b172b1c5467277d36db5308a203a48262d5f278766cf083947d05466",
                "sha256:ff81a1fe7f598ef029d51791e508188068b73c51eb82630e4c7ee762101caae9",
                "sha256:05aaf54e14999de37451bf5f454d3df0a3335b747052d7dd925771b5db20ade5"
            ]
        },
        "Metadata": {
            "LastTagTime": "2021-12-02T10:40:40.070339237+02:00"
        }
    }
]

RepoDigests are added after push. Config and ContainerConfig supposedly hold information about how the image (the last layer) was built. These layer ids are supposedly rather layer diff ids (see below).

Supposedly one history entry per image and its parents + 1 extra entry (and they probably correspond to layers, reverse order):

$ docker history --no-trunc cfc17f8cb22d
IMAGE                                                                     CREATED          CREATED BY                                                                                           SIZE      COMMENT
sha256:cfc17f8cb22d6e17b9a2e88bd1d6c7f9cf5a0fda6bc788e77e3f7ad1d3fdae26   36 minutes ago   /bin/sh -c #(nop) COPY file:c30af0dc159ad65333707b5f57d479de06c1a4bae1566e1dc8e71e8446d68b4d in .    2B        
sha256:79ed4e0c3a63b88f51629582d60429403d78def523821a18b7adc3bd4fe687f3   36 minutes ago   /bin/sh -c echo a > a                                                                                2B        
sha256:021b3423115ff662225e83d7e2606475217de7b55fde83ce3447a54019a77aa2   3 months ago     /bin/sh -c #(nop)  CMD ["/bin/sh"]                                                                   0B        
<missing>                                                                 3 months ago     /bin/sh -c #(nop) ADD file:34eb5c40aa00028921a224d1764ae1b1f3ef710d191e4dfc7df55e0594aa7217 in /     5.59MB    
$ mktemp -d
/tmp/tmp.xqJ8zsHhDh

$ docker save -o /tmp/tmp.xqJ8zsHhDh/image.tar.gz cfc17f8cb22d
$ tar xf /tmp/tmp.xqJ8zsHhDh/image.tar.gz -C /tmp/tmp.xqJ8zsHhDh

$ jq . /tmp/tmp.xqJ8zsHhDh/manifest.json
[
  {
    "Config": "cfc17f8cb22d6e17b9a2e88bd1d6c7f9cf5a0fda6bc788e77e3f7ad1d3fdae26.json",
    "RepoTags": null,
    "Layers": [
      "54b37280869d8e5584390f8a34191a562ef26e2cf4206c88508844dafd07be06/layer.tar",
      "23e77c3142d07ffbffebee18198300b564718b118ae69b57a6ca8abae68c7669/layer.tar",
      "e772a8d92c635349d740d6bf38b85cb6ef562276a1bc2c209123f5502dc629af/layer.tar"
    ]
  }
]

$ jq . /tmp/tmp.xqJ8zsHhDh/cfc17f8cb22d6e17b9a2e88bd1d6c7f9cf5a0fda6bc788e77e3f7ad1d3fdae26.json
{
  "architecture": "amd64",
  "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/sh"
    ],
    "Image": "sha256:79ed4e0c3a63b88f51629582d60429403d78def523821a18b7adc3bd4fe687f3",
    "Volumes": null,
    "WorkingDir": "",
    "Entrypoint": null,
    "OnBuild": null,
    "Labels": null
  },
  "container_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/sh",
      "-c",
      "#(nop) COPY file:c30af0dc159ad65333707b5f57d479de06c1a4bae1566e1dc8e71e8446d68b4d in . "
    ],
    "Image": "sha256:79ed4e0c3a63b88f51629582d60429403d78def523821a18b7adc3bd4fe687f3",
    "Volumes": null,
    "WorkingDir": "",
    "Entrypoint": null,
    "OnBuild": null,
    "Labels": null
  },
  "created": "2021-12-02T08:40:40.000939697Z",
  "docker_version": "20.10.10",
  "history": [
    {
      "created": "2021-08-06T17:19:45.007652184Z",
      "created_by": "/bin/sh -c #(nop) ADD file:34eb5c40aa00028921a224d1764ae1b1f3ef710d191e4dfc7df55e0594aa7217 in / "
    },
    {
      "created": "2021-08-06T17:19:45.183996158Z",
      "created_by": "/bin/sh -c #(nop)  CMD [\"/bin/sh\"]",
      "empty_layer": true
    },
    {
      "created": "2021-12-02T08:40:38.673070939Z",
      "created_by": "/bin/sh -c echo a > a"
    },
    {
      "created": "2021-12-02T08:40:40.000939697Z",
      "created_by": "/bin/sh -c #(nop) COPY file:c30af0dc159ad65333707b5f57d479de06c1a4bae1566e1dc8e71e8446d68b4d in . "
    }
  ],
  "os": "linux",
  "rootfs": {
    "type": "layers",
    "diff_ids": [
      "sha256:bc276c40b172b1c5467277d36db5308a203a48262d5f278766cf083947d05466",
      "sha256:ff81a1fe7f598ef029d51791e508188068b73c51eb82630e4c7ee762101caae9",
      "sha256:05aaf54e14999de37451bf5f454d3df0a3335b747052d7dd925771b5db20ade5"
    ]
  }
}

diff_ids correspond to layer ids from docker inspect.

$ jq . /tmp/tmp.xqJ8zsHhDh/54b37280869d8e5584390f8a34191a562ef26e2cf4206c88508844dafd07be06/json
{
  "id": "54b37280869d8e5584390f8a34191a562ef26e2cf4206c88508844dafd07be06",
  "created": "1970-01-01T03:00:00+03:00",
  "container_config": {
    "Hostname": "",
    "Domainname": "",
    "User": "",
    "AttachStdin": false,
    "AttachStdout": false,
    "AttachStderr": false,
    "Tty": false,
    "OpenStdin": false,
    "StdinOnce": false,
    "Env": null,
    "Cmd": null,
    "Image": "",
    "Volumes": null,
    "WorkingDir": "",
    "Entrypoint": null,
    "OnBuild": null,
    "Labels": null
  },
  "os": "linux"
}

$ tar tf /tmp/tmp.xqJ8zsHhDh/54b37280869d8e5584390f8a34191a562ef26e2cf4206c88508844dafd07be06/layer.tar
bin/
bin/arch
bin/ash
bin/base64
bin/bbconfig
bin/busybox
bin/cat
...

$ jq . /tmp/tmp.xqJ8zsHhDh/23e77c3142d07ffbffebee18198300b564718b118ae69b57a6ca8abae68c7669/json
{
  "id": "23e77c3142d07ffbffebee18198300b564718b118ae69b57a6ca8abae68c7669",
  "parent": "54b37280869d8e5584390f8a34191a562ef26e2cf4206c88508844dafd07be06",
  "created": "1970-01-01T03:00:00+03:00",
  "container_config": {
    "Hostname": "",
    "Domainname": "",
    "User": "",
    "AttachStdin": false,
    "AttachStdout": false,
    "AttachStderr": false,
    "Tty": false,
    "OpenStdin": false,
    "StdinOnce": false,
    "Env": null,
    "Cmd": null,
    "Image": "",
    "Volumes": null,
    "WorkingDir": "",
    "Entrypoint": null,
    "OnBuild": null,
    "Labels": null
  },
  "os": "linux"
}

$ tar tf /tmp/tmp.xqJ8zsHhDh/23e77c3142d07ffbffebee18198300b564718b118ae69b57a6ca8abae68c7669/layer.tar
a

$ jq . /tmp/tmp.xqJ8zsHhDh/e772a8d92c635349d740d6bf38b85cb6ef562276a1bc2c209123f5502dc629af/json
{
  "id": "e772a8d92c635349d740d6bf38b85cb6ef562276a1bc2c209123f5502dc629af",
  "parent": "23e77c3142d07ffbffebee18198300b564718b118ae69b57a6ca8abae68c7669",
  "created": "2021-12-02T08:40:40.000939697Z",
  "container_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/sh",
      "-c",
      "#(nop) COPY file:c30af0dc159ad65333707b5f57d479de06c1a4bae1566e1dc8e71e8446d68b4d in . "
    ],
    "Image": "sha256:79ed4e0c3a63b88f51629582d60429403d78def523821a18b7adc3bd4fe687f3",
    "Volumes": null,
    "WorkingDir": "",
    "Entrypoint": null,
    "OnBuild": null,
    "Labels": null
  },
  "docker_version": "20.10.10",
  "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/sh"
    ],
    "Image": "sha256:79ed4e0c3a63b88f51629582d60429403d78def523821a18b7adc3bd4fe687f3",
    "Volumes": null,
    "WorkingDir": "",
    "Entrypoint": null,
    "OnBuild": null,
    "Labels": null
  },
  "architecture": "amd64",
  "os": "linux"
}

$ tar tf /tmp/tmp.xqJ8zsHhDh/e772a8d92c635349d740d6bf38b85cb6ef562276a1bc2c209123f5502dc629af/layer.tar
b

Push the image:

$ docker push registry.com/test-img:v1
The push refers to repository [registry.com/test-img]
05aaf54e1499: Pushed
ff81a1fe7f59: Pushed
bc276c40b172: Pushed
v1: digest: sha256:1ed6da69b82018bee5dfc0ac48b24890cd10044072058e9d97a6327d50be2f73 size: 940

Here docker lists diff ids and the image digest (repo digest).

List repositories (images):

$ curl -sS https://registry.com/v2/_catalog | jq
{
  "repositories": [
    ...
    "test-img"
  ]
}

List image tags:

$ curl -sS https://registry.com/v2/test-img/tags/list | jq
{
  "name": "test-img",
  "tags": [
    "v1"
  ]
}

Fetch a manifest:

$ curl -sS https://registry.com/v2/test-img/manifests/v1 | jq
{
  "schemaVersion": 1,
  "name": "test-img",
  "tag": "v1",
  "architecture": "amd64",
  "fsLayers": [
    {
      "blobSum": "sha256:080856f10b82e60fbaa06a48b2354f0c4a1f9350575300dc85b73b5b2d0b617a"
    },
    {
      "blobSum": "sha256:33db3b58b01ffbbf2e854669caf83de9e73a29ae61673c126af9225f92e8280a"
    },
    {
      "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
    },
    {
      "blobSum": "sha256:29291e31a76a7e560b9b7ad3cada56e8c18d50a96cca8a2573e4f4689d7aca77"
    }
  ],
  "history": [
    {
      "v1Compatibility": "{\"architecture\":\"amd64\",\"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/sh\"],\"Image\":\"sha256:79ed4e0c3a63b88f51629582d60429403d78def523821a18b7adc3bd4fe687f3\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"container_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/sh\",\"-c\",\"#(nop) COPY file:c30af0dc159ad65333707b5f57d479de06c1a4bae1566e1dc8e71e8446d68b4d in . \"],\"Image\":\"sha256:79ed4e0c3a63b88f51629582d60429403d78def523821a18b7adc3bd4fe687f3\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"created\":\"2021-12-02T08:40:40.000939697Z\",\"docker_version\":\"20.10.10\",\"id\":\"dd7bcade681d1b416b3153d7f09bb094c80519b91a6d9a62a2214473a264be42\",\"os\":\"linux\",\"parent\":\"55a899ffb69bdf89764b379a3067b977727af41a3358f865b8247e0745b38bb6\"}"
    },
    {
      "v1Compatibility": "{\"id\":\"55a899ffb69bdf89764b379a3067b977727af41a3358f865b8247e0745b38bb6\",\"parent\":\"e6cce097685236ee2f35833ebb5261dd0efbc2a7eb49de0955dadd3628e4167e\",\"created\":\"2021-12-02T08:40:38.673070939Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c echo a \\u003e a\"]}}"
    },
    {
      "v1Compatibility": "{\"id\":\"e6cce097685236ee2f35833ebb5261dd0efbc2a7eb49de0955dadd3628e4167e\",\"parent\":\"697f196e745a3ecabd1ceb613885d119977580a166269e7159909d10edb8101f\",\"created\":\"2021-08-06T17:19:45.183996158Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop)  CMD [\\\"/bin/sh\\\"]\"]},\"throwaway\":true}"
    },
    {
      "v1Compatibility": "{\"id\":\"697f196e745a3ecabd1ceb613885d119977580a166269e7159909d10edb8101f\",\"created\":\"2021-08-06T17:19:45.007652184Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) ADD file:34eb5c40aa00028921a224d1764ae1b1f3ef710d191e4dfc7df55e0594aa7217 in / \"]}}"
    }
  ],
  "signatures": [...]
}

History and layers are in reverse order. These layer ids differ from the local layer ids.

Fetch layers:

$ curl -sS https://registry.com/v2/test-img/blobs/sha256:080856f10b82e60fbaa06a48b2354f0c4a1f9350575300dc85b73b5b2d0b617a | tar tzf -
b

$ curl -sS https://registry.com/v2/test-img/blobs/sha256:33db3b58b01ffbbf2e854669caf83de9e73a29ae61673c126af9225f92e8280a | tar tzf -
a

$ curl -sS https://registry.com/v2/test-img/blobs/sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4 | tar tzf -

$ curl -sS https://registry.com/v2/test-img/blobs/sha256:29291e31a76a7e560b9b7ad3cada56e8c18d50a96cca8a2573e4f4689d7aca77 | tar tzf -
bin/
bin/arch
bin/ash
bin/base64
bin/bbconfig
bin/busybox
bin/cat
...

One can specify a digest in place of a tag (this probably corresponds to the revisions dir on a docker registry's filesystem):

$ curl -sS https://registry.com/v2/test-img/manifests/sha256:1ed6da69b82018bee5dfc0ac48b24890cd10044072058e9d97a6327d50be2f73 | jq
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
  "config": {
    "mediaType": "application/vnd.docker.container.image.v1+json",
    "size": 1837,
    "digest": "sha256:cfc17f8cb22d6e17b9a2e88bd1d6c7f9cf5a0fda6bc788e77e3f7ad1d3fdae26"
  },
  "layers": [
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 2813006,
      "digest": "sha256:29291e31a76a7e560b9b7ad3cada56e8c18d50a96cca8a2573e4f4689d7aca77"
    },
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 97,
      "digest": "sha256:33db3b58b01ffbbf2e854669caf83de9e73a29ae61673c126af9225f92e8280a"
    },
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 98,
      "digest": "sha256:080856f10b82e60fbaa06a48b2354f0c4a1f9350575300dc85b73b5b2d0b617a"
    }
  ]
}

Only non-empty layers here.

An image config:

$ curl -sS https://registry.com/v2/test-img/blobs/sha256:cfc17f8cb22d6e17b9a2e88bd1d6c7f9cf5a0fda6bc788e77e3f7ad1d3fdae26 | jq
{
  "architecture": "amd64",
  "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/sh"
    ],
    "Image": "sha256:79ed4e0c3a63b88f51629582d60429403d78def523821a18b7adc3bd4fe687f3",
    "Volumes": null,
    "WorkingDir": "",
    "Entrypoint": null,
    "OnBuild": null,
    "Labels": null
  },
  "container_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/sh",
      "-c",
      "#(nop) COPY file:c30af0dc159ad65333707b5f57d479de06c1a4bae1566e1dc8e71e8446d68b4d in . "
    ],
    "Image": "sha256:79ed4e0c3a63b88f51629582d60429403d78def523821a18b7adc3bd4fe687f3",
    "Volumes": null,
    "WorkingDir": "",
    "Entrypoint": null,
    "OnBuild": null,
    "Labels": null
  },
  "created": "2021-12-02T08:40:40.000939697Z",
  "docker_version": "20.10.10",
  "history": [
    {
      "created": "2021-08-06T17:19:45.007652184Z",
      "created_by": "/bin/sh -c #(nop) ADD file:34eb5c40aa00028921a224d1764ae1b1f3ef710d191e4dfc7df55e0594aa7217 in / "
    },
    {
      "created": "2021-08-06T17:19:45.183996158Z",
      "created_by": "/bin/sh -c #(nop)  CMD [\"/bin/sh\"]",
      "empty_layer": true
    },
    {
      "created": "2021-12-02T08:40:38.673070939Z",
      "created_by": "/bin/sh -c echo a > a"
    },
    {
      "created": "2021-12-02T08:40:40.000939697Z",
      "created_by": "/bin/sh -c #(nop) COPY file:c30af0dc159ad65333707b5f57d479de06c1a4bae1566e1dc8e71e8446d68b4d in . "
    }
  ],
  "os": "linux",
  "rootfs": {
    "type": "layers",
    "diff_ids": [
      "sha256:bc276c40b172b1c5467277d36db5308a203a48262d5f278766cf083947d05466",
      "sha256:ff81a1fe7f598ef029d51791e508188068b73c51eb82630e4c7ee762101caae9",
      "sha256:05aaf54e14999de37451bf5f454d3df0a3335b747052d7dd925771b5db20ade5"
    ]
  }
}
$ ssh root@registry.com tree /var/lib/docker/volumes/registry/_data/docker/registry/v2/repositories/test-img
/var/lib/docker/volumes/registry/_data/docker/registry/v2/repositories/test-img
├── _layers
│   └── sha256
│       ├── 080856f10b82e60fbaa06a48b2354f0c4a1f9350575300dc85b73b5b2d0b617a
│       │   └── link
sha256:080856f10b82e60fbaa06a48b2354f0c4a1f9350575300dc85b73b5b2d0b617a
│       ├── 29291e31a76a7e560b9b7ad3cada56e8c18d50a96cca8a2573e4f4689d7aca77
│       │   └── link -> sha256:29291e31a76a7e560b9b7ad3cada56e8c18d50a96cca8a2573e4f4689d7aca77
│       ├── 33db3b58b01ffbbf2e854669caf83de9e73a29ae61673c126af9225f92e8280a
│       │   └── link -> sha256:33db3b58b01ffbbf2e854669caf83de9e73a29ae61673c126af9225f92e8280a
│       ├── a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
│       │   └── link -> sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
│       └── cfc17f8cb22d6e17b9a2e88bd1d6c7f9cf5a0fda6bc788e77e3f7ad1d3fdae26
│           └── link -> sha256:cfc17f8cb22d6e17b9a2e88bd1d6c7f9cf5a0fda6bc788e77e3f7ad1d3fdae26
├── _manifests
│   ├── revisions
│   │   └── sha256
│   │       └── 1ed6da69b82018bee5dfc0ac48b24890cd10044072058e9d97a6327d50be2f73
│   │           └── link -> sha256:1ed6da69b82018bee5dfc0ac48b24890cd10044072058e9d97a6327d50be2f73
│   └── tags
│       └── v1
│           ├── current
│           │   └── link -> sha256:1ed6da69b82018bee5dfc0ac48b24890cd10044072058e9d97a6327d50be2f73
│           └── index
│               └── sha256
│                   └── 1ed6da69b82018bee5dfc0ac48b24890cd10044072058e9d97a6327d50be2f73
│                       └── link -> sha256:1ed6da69b82018bee5dfc0ac48b24890cd10044072058e9d97a6327d50be2f73
└── _uploads

18 directories, 8 files

You can delete a manifests:

$ curl -sS -X DELETE https://registry.com/v2/test-img/manifests/sha256:1ed6da69b82018bee5dfc0ac48b24890cd10044072058e9d97a6327d50be2f73

But that doesn't delete the blobs:

$ ssh root@registry.com tree /var/lib/docker/volumes/registry/_data/docker/registry/v2/repositories/test-img
/var/lib/docker/volumes/registry/_data/docker/registry/v2/repositories/test-img
├── _layers
│   └── sha256
│       ├── 080856f10b82e60fbaa06a48b2354f0c4a1f9350575300dc85b73b5b2d0b617a
│       │   └── link
│       ├── 29291e31a76a7e560b9b7ad3cada56e8c18d50a96cca8a2573e4f4689d7aca77
│       │   └── link -> sha256:29291e31a76a7e560b9b7ad3cada56e8c18d50a96cca8a2573e4f4689d7aca77
│       ├── 33db3b58b01ffbbf2e854669caf83de9e73a29ae61673c126af9225f92e8280a
│       │   └── link -> sha256:33db3b58b01ffbbf2e854669caf83de9e73a29ae61673c126af9225f92e8280a
│       ├── a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
│       │   └── link -> sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
│       └── cfc17f8cb22d6e17b9a2e88bd1d6c7f9cf5a0fda6bc788e77e3f7ad1d3fdae26
│           └── link -> sha256:cfc17f8cb22d6e17b9a2e88bd1d6c7f9cf5a0fda6bc788e77e3f7ad1d3fdae26
├── _manifests
│   ├── revisions
│   │   └── sha256
│   │       └── 1ed6da69b82018bee5dfc0ac48b24890cd10044072058e9d97a6327d50be2f73
│   └── tags
└── _uploads

13 directories, 5 files

And you can delete a blob:

$ curl -sS -X DELETE https://registry.com/v2/test-img/blobs/sha256:080856f10b82e60fbaa06a48b2354f0c4a1f9350575300dc85b73b5b2d0b617a

$ ssh root@registry.com tree /var/lib/docker/volumes/registry/_data/docker/registry/v2/repositories/test-img
/var/lib/docker/volumes/registry/_data/docker/registry/v2/repositories/test-img
├── _layers
│   └── sha256
│       ├── 080856f10b82e60fbaa06a48b2354f0c4a1f9350575300dc85b73b5b2d0b617a
│       ├── 29291e31a76a7e560b9b7ad3cada56e8c18d50a96cca8a2573e4f4689d7aca77
│       │   └── link -> sha256:29291e31a76a7e560b9b7ad3cada56e8c18d50a96cca8a2573e4f4689d7aca77
│       ├── 33db3b58b01ffbbf2e854669caf83de9e73a29ae61673c126af9225f92e8280a
│       │   └── link -> sha256:33db3b58b01ffbbf2e854669caf83de9e73a29ae61673c126af9225f92e8280a
│       ├── a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
│       │   └── link -> sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
│       └── cfc17f8cb22d6e17b9a2e88bd1d6c7f9cf5a0fda6bc788e77e3f7ad1d3fdae26
│           └── link -> sha256:cfc17f8cb22d6e17b9a2e88bd1d6c7f9cf5a0fda6bc788e77e3f7ad1d3fdae26
├── _manifests
│   ├── revisions
│   │   └── sha256
│   │       └── 1ed6da69b82018bee5dfc0ac48b24890cd10044072058e9d97a6327d50be2f73
│   └── tags
└── _uploads

13 directories, 4 files

But the data doesn't get deleted:

$ ssh root@registry.com ls /var/lib/docker/volumes/registry/_data/docker/registry/v2/blobs/sha256/08/080856f10b82e60fbaa06a48b2354f0c4a1f9350575300dc85b73b5b2d0b617a/data
/var/lib/docker/volumes/registry/_data/docker/registry/v2/blobs/sha256/08/080856f10b82e60fbaa06a48b2354f0c4a1f9350575300dc85b73b5b2d0b617a/data
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment