DEV Community

Vecha Sumanth
Vecha Sumanth

Posted on

Understanding the Docker Registry Structure - Gitlab

Overview

With the Docker container registry image, Gitlab allows the chosen few (Hail DevOps) to integrate a private container registry seamlessly. A couple of edits in the gitlab.rb file and you should be good to go.

The Docker container registry is a pretty stable and reliable piece of software which makes the life of a DevOps Engineer slightly easy. Although there would be some cases where you'd like to play with it. (ensuring chaos ensues)

this-is-fine-fire.gif

Finding the treasure

When the Container Registry Image is run by default the rootdirectory set as /var/docker/registry. Which should be the same in most cases.

On mild forensics the file structure comes out to be as shown as below -

- /var/docker/registry
    - v2
        - blobs
        - repositories
Enter fullscreen mode Exit fullscreen mode

v2 corresponds to the Docker Registry API version which Version 2 in this case.

On further digging the repositories directory hosts the following sub-directories -

- repositories
    - gitlab-test-user
        - gitlab-test-repo
            - _layers
            - _manifests
                - revisions
                - tags
                    - sample-tag
                        - current
                            - link
                        - index
            _ _uploads

Enter fullscreen mode Exit fullscreen mode

Phew! That's a long list, but the most important of all is the link component. The link itself is not the image but an ID.

"Then where is the Image?", you ask.

The "Image Data" is stored in the blobs directory under the v2 directory. Opening up blobs gives us the this -

- blobs
    - sha256
        - 3b
        - cb
        - f6
            - f662ea83eddb8ce7e979cb6c09527feace32d32500e027fa87bf5362d732af16
                - data
Enter fullscreen mode Exit fullscreen mode

Haha, Finally the data!
Uhmmm not yet.

{
    "schemaVersion": 2,
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json"
    "config": {
        "mediaType": "application/vnd.docker.container.image.v1+json"
        "size": 1619,
        "digest"; "sha256:3b0372d60921e1cc0c017732ff6d41f8e4880246a6d9c8c9d101edc1726a79ab"
    },
    "layers": [
        {
            "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
            "size": 2813316,
            "digest": "sha256:cbdbe7a5bc2a134caBec91be58565ec07d037386d1f1d8385412d224deafca08"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

This is rather a JSON document containing details of the image.

The config digest ("sha256:3b0372d60921e1cc0c017732ff6d41f8e4880246a6d9c8c9d101edc1726a79ab") is a link to a document that will instruct docker on how to build the image. It can be found under blobs/sha256/3b.

One thing to understand is that a Docker Image is not a single chunk of data rather it is a collection of layers. This is a really efficient technique to store data as this helps in not storing redundant pieces of information as we will see later.

Now moving on to the second part of the above "data" file is the link to where the layers of the image are stored. Here we have the digest as "sha256: cbdbe7a5bc2a134caBec91be58565ec07d037386d1f1d8385412d224deafca08" which again can be found under blobs/sha256/cb, you can now see the Image in its layers form. Since we have only one layer here, that itself is the image or rather the ingredient of the image which will be used by docker to create the image.

The layers themselves are single pieces but when combined make up the image. This helps in saving up space.

Take a scenario where the same image is being pushed into the registry, this time rather than again storing the redundant piece of data, docker will link to the same image layer as the previous one. Saving us with some space.

Considering the case where the are some changes to the image and is pushed to the same or a different repository, docker will create a new layer which is the diff (just the modified part) part of the new image and simply create a link and add this to the configuration file which we saw earlier.

{
    "schemaVersion": 2,
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json"
    "config": {
        "mediaType": "application/vnd.docker. container. image.v1+json"
        "size": 1619,
        "digest"; "sha256:3b0372d60921e1cc0c017732ff6d41f8e4880246a6d9c8c9d101edc1726a79ab"
    },
    "layers": [
        {
            "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
            "size": 2813316,
            "digest": "sha256:cbdbe7a5bc2a134caBec91be58565ec07d037386d1f1d8385412d224deafca08"
        },
        {
            "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
            "size": 109,
            "digest": "sha256:5110abe04d9e848d121feb3cc36dd0ec20465f6f67f6dc49699ea408bc244188"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

The modified part of the image forms a new layer and the link to that layer has been added to the file.

Summing up, whenever we do a docker pull to the registry it will go and fetch the link under the respective repository, which points towards the manifest file in blobs containing the recipe (instructions) and the ingredients (layers) which docker will then use to make the image.

For further explanation - Reference

Thanks

Top comments (1)

Collapse
 
chideracode profile image
Chidera Humphrey

Thanks for sharing.