2022-12-22
Docker images are a powerful tool for packaging and deploying applications, but it can be difficult to understand the differences between two images. In this blog, we will demonstrate how to compare two images of a Node.js application using several popular tools. We will use docker inspect
to view the low-level details of an image, container-diff
to compare files and configuration changes, and dive
to visualize the layers of an image. Through this comparison, we will learn how to identify the differences between two images and understand how those differences may impact the performance, security and size of the images. This will help us to understand how to select the best image for our use case, and how to troubleshoot issues.
Firstly, we can use docker inspect
to check the low-level details of an image.
The docker inspect
command is used to view low-level details of a Docker image. When you run docker inspect
on an image, it returns a JSON object that contains information about the image, including metadata, config, history, and the layer's filesystems. Here are a few examples of the information that you can get from running docker inspect
on an image:
Id
: The ID of the image.RepoTags
: The names and tags of the image.Created
: The date and time when the image was created.Size
: The size of the image.Config
: The configuration of the image, including environment variables, entrypoint, and command.ContainerConfig
: The config of the container created from the image.Layers
: The layers of the image and their digests.Labels
: The labels of the image.# single stage build
➜ test1000 git:(main) ✗ docker inspect 8c5368c4b334
[
{
"Id": "sha256:8c5368c4b3343455c851ba28c2712c344ef9221b76903789024774d9bfb36f46",
"RepoTags": [
"davidzhangw/coffee:v2"
],
"RepoDigests": [
"davidzhangw/coffee@sha256:5d8784dcbcf2196910b8b2e1d1650217aec5b1b262831b50df99aa9d31d8fb26"
],
"Parent": "",
"Comment": "buildkit.dockerfile.v0",
"Created": "2023-01-12T03:58:47.156540625Z",
"Container": "",
"ContainerConfig": {
"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
},
"DockerVersion": "",
"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",
"NODE_VERSION=19.4.0",
"YARN_VERSION=1.22.19"
],
"Cmd": [
"npm",
"run",
"start"
],
"ArgsEscaped": true,
"Image": "",
"Volumes": null,
"WorkingDir": "/app",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 1998434757,
"VirtualSize": 1998434757,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/lxw5ya6tvive6tluustvn53za/diff:/var/lib/docker/overlay2/pofdzxu8szk50mfkp2e6opo34/diff:/var/lib/docker/overlay2/g8e0iuznahft9976n38v95my6/diff:/var/lib/docker/overlay2/p48ndp1tsmpxxsmtt0ks4hnht/diff:/var/lib/docker/overlay2/88mblz57wfcfsxp6t1ghety3c/diff:/var/lib/docker/overlay2/b13186853ac88f9ab23b6b4ef28f50afd30c9d2505d76a6dc66998cb19af0142/diff:/var/lib/docker/overlay2/bad42c6df0a4e63e6c00b18a4c29fb59894040c2884d090a5f0b9f7a0ea667fb/diff:/var/lib/docker/overlay2/b4b0bc3d9289c5d2874884c6cdda952bb3274dff3173fff7abad891593b4ff29/diff:/var/lib/docker/overlay2/82092b666d220f3dea0fcca899acec4ccd1fe1b362e1c74466f35f2161b28f47/diff",
"MergedDir": "/var/lib/docker/overlay2/v492rnnl73t0vhb3c8b497rec/merged",
"UpperDir": "/var/lib/docker/overlay2/v492rnnl73t0vhb3c8b497rec/diff",
"WorkDir": "/var/lib/docker/overlay2/v492rnnl73t0vhb3c8b497rec/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:8e012198eea15b2554b07014081c85fec4967a1b9cc4b65bd9a4bce3ae1c0c88",
"sha256:a49d675cd49c631e995be8fa05ffffc412bba04820ebdaf654e92f317120923c",
"sha256:887a67b27874c174f149eacb3eff9f11999767cdf731a410a9d333933247b46d",
"sha256:6d0edcc4175ba7264c14e60bef68919164af84d72bc1a4f9f99acacb42f25d83",
"sha256:44ac598f28410ce3ece1ab2cd349cf781defb75c6730aec009dada21457bb991",
"sha256:99df869b10b55218bca6421f0d52f737b7944a210a08b0627df455ff9b4085f3",
"sha256:24262d08a858d3d458989039a85619f3a558be7d98f19deddb564357a1d800a2",
"sha256:6904210f6073486388c2dfedada7e7113ea0854bf35274dd7ad589f7cfba7967",
"sha256:0cf1fdea0d82dd6f58393c39d37d1b576db0b54712b95eba8bace4a56b34e2b9",
"sha256:175344ff0f2bb74487c29590eeb3de1e245b7896ac6d7a468372a3851b790bd8"
]
},
"Metadata": {
"LastTagTime": "2023-01-12T03:58:51.680480585Z"
}
}
]
# multi-stage build
➜ test1000 git:(main) ✗ docker inspect b4a554029c8d
[
{
"Id": "sha256:b4a554029c8d40f0f537e70258e1ea4e65e7714d5f4d6efbcb01d2d218307e69",
"RepoTags": [
"davidzhangw/coffee:v3"
],
"RepoDigests": [
"davidzhangw/coffee@sha256:c069c18560f6a7f474ea0782a59052582e4c70979ddf00373a78842ee15f13b0"
],
"Parent": "",
"Comment": "buildkit.dockerfile.v0",
"Created": "2023-01-20T09:48:06.929174555Z",
"Container": "",
"ContainerConfig": {
"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
},
"DockerVersion": "",
"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",
"NODE_VERSION=19.4.0",
"YARN_VERSION=1.22.19"
],
"Cmd": [
"npm",
"run",
"start"
],
"ArgsEscaped": true,
"Image": "",
"Volumes": null,
"WorkingDir": "/app",
"Entrypoint": [
"docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 952727102,
"VirtualSize": 952727102,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/ktmaji0naxpdssgksmdvty2qz/diff:/var/lib/docker/overlay2/ive3ckpnacx6xws0lkver3cpt/diff:/var/lib/docker/overlay2/k71s51gqnetpwigia8tk1gw31/diff:/var/lib/docker/overlay2/lkpceob4bzn7k3f1tloaqs947/diff:/var/lib/docker/overlay2/88mblz57wfcfsxp6t1ghety3c/diff:/var/lib/docker/overlay2/b13186853ac88f9ab23b6b4ef28f50afd30c9d2505d76a6dc66998cb19af0142/diff:/var/lib/docker/overlay2/bad42c6df0a4e63e6c00b18a4c29fb59894040c2884d090a5f0b9f7a0ea667fb/diff:/var/lib/docker/overlay2/b4b0bc3d9289c5d2874884c6cdda952bb3274dff3173fff7abad891593b4ff29/diff:/var/lib/docker/overlay2/82092b666d220f3dea0fcca899acec4ccd1fe1b362e1c74466f35f2161b28f47/diff",
"MergedDir": "/var/lib/docker/overlay2/ff1osvxhtdl3evp6nkomb15lm/merged",
"UpperDir": "/var/lib/docker/overlay2/ff1osvxhtdl3evp6nkomb15lm/diff",
"WorkDir": "/var/lib/docker/overlay2/ff1osvxhtdl3evp6nkomb15lm/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:8e012198eea15b2554b07014081c85fec4967a1b9cc4b65bd9a4bce3ae1c0c88",
"sha256:a49d675cd49c631e995be8fa05ffffc412bba04820ebdaf654e92f317120923c",
"sha256:887a67b27874c174f149eacb3eff9f11999767cdf731a410a9d333933247b46d",
"sha256:6d0edcc4175ba7264c14e60bef68919164af84d72bc1a4f9f99acacb42f25d83",
"sha256:44ac598f28410ce3ece1ab2cd349cf781defb75c6730aec009dada21457bb991",
"sha256:451ec394cf2cf0355952c5199855e3de0d446291bca48e0928435122a3286a0d",
"sha256:2bb99a439a5a606aa1c5096d2d744d0da75e0f2e248df95d9c2878999641b989",
"sha256:27ebabaecb857acccb1a7e34573e197c8633f8fa7ad6fbc48fee61b61544a593",
"sha256:c60cbc4de8352216907ddd35330052f8d3b421504cb9e8a83a599175e3971249",
"sha256:9c94ddf41eb611b1ac1f6403c001237d47cba4e688685ce003d556da973b0c07"
]
},
"Metadata": {
"LastTagTime": "2023-01-20T09:48:11.007232668Z"
}
}
]
container-diff
is a command-line tool that allows you to compare the differences between two Docker images. It can show you the changes in files, environment variables, and configuration between two images.
To compare two images, you can run the command container-diff diff <image1> <image2>
. It will show the differences between the two images, indicating which files were added, modified, or deleted, as well as any changes to environment variables or configuration. The output is presented in a unified diff format, which is similar to the output of the diff
command.
<aside>
👉 Please note that we use daemon
to refer the local docker image.
</aside>
Please refer to Reference section to install container-diff
.