What is inside a Docker image?

What is inside a Docker image?

Some time ago, I had to modify one application which did not have a Dockerfile in its source code repository. Apparently, someone forgot to commit it. I could make the changes, but how do I deploy it?

Fortunately, I could download the previous docker image from the Docker repository and check what was inside. So, how do we check what is inside a Docker image?

As the first step, we must save a Docker image as a tar file.

1
docker save — output image.tar <image name>

Now, we can create a new directory and unpack the tar file into it.

1
2
mkdir extracted
tar -xf image.tar -C extracted

The directory contains directories for every layer in this docker image. In the case of my image, the content of the tar file looks like this:

1
2
3
4
5
6
7
8
0e5176443be87e22a05ce7b9e28b623289f6722465fb9c3579c6b98c2419aa89.json
4bfac6fe3333e456db496465d112632e00986bf42400faee457a87c8db947b5f
56ce86a9ea9ac8876df7cc6ed93044050915d43fae7db3f33c78521e2e80a43d
a1700ea4465fc48b04e06501ae0dd47a21bc95eddbf90fde6f9c63e38c819da0
bfc566732015e74554c940abfdedb5ca215be6a392cad0f189b171298527cc09
cd15ebb84d8e12670ea5f1757b2b45d00496d73a0d0c688e2896928b52a707bc
manifest.json
repositories

Let’s look at the manifest.json file. It contains an array of docker layers listed in order of their creation.

1
2
3
4
5
6
7
8
9
10
[{
"Config": "0e5176443be87e22a05ce7b9e28b623289f6722465fb9c3579c6b98c2419aa89.json",
"RepoTags": ["sbt:latest"],
"Layers": [
"4bfac6fe3333e456db496465d112632e00986bf42400faee457a87c8db947b5f/layer.tar",
"bfc566732015e74554c940abfdedb5ca215be6a392cad0f189b171298527cc09/layer.tar",
"cd15ebb84d8e12670ea5f1757b2b45d00496d73a0d0c688e2896928b52a707bc/layer.tar",
"56ce86a9ea9ac8876df7cc6ed93044050915d43fae7db3f33c78521e2e80a43d/layer.tar",
"a1700ea4465fc48b04e06501ae0dd47a21bc95eddbf90fde6f9c63e38c819da0/layer.tar"]
}]

We see that the last layer is defined in the file “a1700ea4465fc48b04e06501ae0dd47a21bc95eddbf90fde6f9c63e38c819da0/layer.tar”. For demonstration purposes, I unpacked the image created while writing the blog post about building a project inside a Docker container.

Hence I expect that the last layer contains files modified while creating a new user. Let’s verify that.

In the directory, there is a layer.tar file which I must unpack. After unpacking it, I see that it contains an empty “/home/appuser” directory and some files in the “/etc” directory. Which files does it contain? Only the “/etc” files which have been modified in the last step of Dockerfile. In this case, the files containing information about Linux users.

1
2
> ls etc
group group- passwd passwd- shadow shadow-

We can repeat the same steps to see modifications done in every other layer of the docker image.

Do you want to show your product/service to 25000 data science enthusiasts every month? I am looking for companies which would like to become a partner of this blog.

Are you interested? Is your employer interested? Here are the details of the offer.

There is one more thing. At the end of the Dockerfile, I defined the default user. Where does it store this information?

To find this, we must once again look at the directory which contains the last Docker layer. There is a JSON file in it which configures the working directory and the user. In the case of my image, the configuration looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
"config": {
"Hostname": "",
"Domainname": "",
"User": "appuser",
"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:/usr/lib/jvm/java-1.8-openjdk/jre/bin:/usr/lib/jvm/java-1.8-openjdk/bin",
"LANG=C.UTF-8",
"JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk/jre",
"JAVA_VERSION=8u171",
"JAVA_ALPINE_VERSION=8.171.11-r0",
"SCALA_VERSION=2.12.7",
"SBT_VERSION=1.2.3"
],
"Cmd": [
"/bin/sh"
],
"ArgsEscaped": true,
"Image": "sha256:f48ad349b9aafb3e1512619fbf43307f5ab7a464c87b38fdaace51d788317aee",
"Volumes": null,
"WorkingDir": "/home/appuser",
"Entrypoint": null,
"OnBuild": [],
"Labels": null
}

Remember to share on social media!
If you like this text, please share it on Facebook/Twitter/LinkedIn/Reddit or other social media.

If you watch programming live streams, check out my YouTube channel.
You can also follow me on Twitter: @mikulskibartosz

If you want to hire me, send me a message on LinkedIn or Twitter.


If this article was helpful, consider donating to WWF or any other charity of your choice.
Bartosz Mikulski
Bartosz Mikulski * data scientist / software engineer * conference speaker * organizer of School of A.I. meetups in Poznań * co-founder of Software Craftsmanship Poznan & Poznan Scala User Group