Docker With Spring Boot: Part 3— Inspect Images

Vinod Madubashana
Javarevisited
Published in
5 min readFeb 19, 2024
Photo by Rubaitul Azad on Unsplash

I give some options for creating images in the first two parts of this series. This part lets us deepen our knowledge of images by inspecting them.

As we discussed, the docker image is created with layers; all these are just nothing but files and directories. The union file systems can combine those files and directories to view as a single entity. There are many storage drivers available. The default one used in most cases is the Overlay2 driver. Check the docker doc linked attached if you are interested in learning more about lear these storage options.

When using docker files it is easy to map the contents of each layer and assume the content. But we also use different declarative approaches like build packs to build our images. So I think it is good to know what kind of options are available for us to examine such created images. This knowledge might also help optimize layers of our existing images.

Extract a docker image into a tar

As I said since each directory is a set of files it should be possible to extract them. The docker save command helps to do this. Here I am using the docker image that is created using the gradle plugin which uses cloudnative buildpacks. More details are available in the previous part of this series.

docker save -o output.tar gradle-task-build

The manifest file contains the references to other layers and a reference to a config file

The config file contains more details like root file system details, layer hashes, and entry point info.

Although when we created these images we didn't know what these details were now with the help of this we know more details like entry point. We can also extract each layer and see what's inside it.

The usefulness of this kind of extraction is very limited. But this would be easier to visualize with some kind of diffing tool which we discuss at the end of this article. Before that let's use docker inspect to inspect images.

docker inspect

This is a docker command that can be easily executed to inspect configs and layering info without extracting it into tar.

docker inspect gradle-task-build

You might easily understand all the details in the output of this command except for the GraphDriver section. So I will discuss more about these details.

This section contains details about storage. The name here is the storage drive name which is overlay2 as I explained earlier too. The Data section shows the details of where the actual layers are stored in the docker host. It is well explained in this documentation.

The image layer is the lowerdir and the container layer is the upperdir. If the image has multiple layers, multiple lowerdir directories are used. The unified view is exposed through a directory called merged which is effectively the containers mount point.

Now you know that images are not a magical thing all of them are available in the docker host as files and directories. You can examine them. If you use the docker desktop in Windows like me you might not have direct access to the underlying docker host virtual machine. But with the help of privileged mode and nsenter command in Debian systems can be used as a trick to get access to this virtual machine. Don’t need to understand this just run it it will give you a shell that is inside the virtual machine.

docker container run --rm -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh

That is another reason not to keep any secret data in any of the layers because they will be available in the docker host and if it is compromised those data also will be compromised.

Again this is also good to know but might rarely be useful in most cases because you have to navigate it manually. Let’s see a better tool for the job

dive

A tool for exploring a docker image, layer contents, and discovering ways to shrink the size of your Docker/OCI image.

dive is a handy tool that overcomes problems with the above solutions. You can visualize the changes.

dive gradle-task-build

The UI is not complicated and easy to navigate. We can use this to understand each layer and might give some insights to further optimizations. In our case, it was able to see that cloud-native buildpacks separate our application dependencies and application code into separate layers to optimize the layer caching.

So now I think you have deepened your knowledge of docker images. Let’s extend this knowledge further in the next part of this series which describes image versioning and registries.

Resources

--

--

Vinod Madubashana
Javarevisited

Full-stack Developer, Java, Spring Boot, React, Angular, AWS ...