docker: how to show the diffs between 2 images

Docker

Docker Problem Overview


I have a Dockerfile with a sequence of RUN instructions that execute "apt-get install"s; for example, a couple of lines:

RUN apt-get install -y tree
RUN apt-get install -y git

After having executed "docker build", if I then execute "docker images -a", I see the listing of all the base-child-child-.... images that were created during the build.

I'd like to see a list of all of the packages that were installed when the "apt-get install -y git" line was executed (including the dependent packages that may have also been installed, besides the git packages).

Note: I believe that the "docker diff" command shows the diffs between a container and the image from which it was started. Instead I'd like the diffs between 2 images (of the same lineage): the "tree" and "git" image IDs. Is this possible?

Thanks.

Docker Solutions


Solution 1 - Docker

Have a look at :

https://github.com/GoogleCloudPlatform/container-diff

This tool can diff local or remote docker images and can do so without requiring docker to be installed. It has file as well as package level "differs" (for example: apt, npm, and pip) so that you can more easily see the differences in packages that have changed between two docker images.

Disclaimer: I am a contributor to this project

Solution 2 - Docker

This one worked for me:

docker run -it e5cba87ecd29 bash -c 'find /path/to/files -type f | sort  | xargs -I{} sha512sum {}' > /tmp/dockerfiles.e5cba87ecd29.txt
docker run -it b1d19fe1a941 bash -c 'find /path/to/files -type f | sort  | xargs -I{} sha512sum {}' > /tmp/dockerfiles.b1d19fe1a941.txt
meld /tmp/dockerfiles*

Where e5cba87ecd29 and b1d19fe1a941 are images I am interested in and /path/to/files is a directory which could be "/". It lists all files, sorts it and add hash to it just in case. And meld highlights all the differences.

Solution 3 - Docker

I suppose you could send both images' file systems to tarballs via docker export CONTAINER_ID or docker save IMAGE_ID (updated based on comments)

Then use whatever tool you like to diff the file systems - Git, Rdiff, etc.

Solution 4 - Docker

It is now 2019 and I just found a useful tool which was released in late 2017. https://opensource.googleblog.com/2017/11/container-diff-for-comparing-container-images.html

The following content is from container-diff github page:

container-diff diff <img1> <img2> --type=history  [History]
container-diff diff <img1> <img2> --type=file  [File System]
container-diff diff <img1> <img2> --type=size  [Size]
container-diff diff <img1> <img2> --type=rpm  [RPM]
container-diff diff <img1> <img2> --type=pip  [Pip]
container-diff diff <img1> <img2> --type=apt  [Apt]
container-diff diff <img1> <img2> --type=node  [Node]

You can similarly run many analyzers at once:

container-diff diff <img1> <img2> --type=history --type=apt --type=node

Solution 5 - Docker

Each RUN instruction creates a new container and you can inspect what a container changed by using docker diff <container>.

So after building your dockerfile, run docker ps -a to get a list of the containers the buildfile created. It should look something like:

CONTAINER ID  IMAGE        COMMAND               CREATED        STATUS ...
53d7dadafee7  f71e394eb0fc /bin/sh -c apt-get i  7 minutes ago  Exit 0 ...
...

Now you can do do docker diff 53d7dadafee7 to see what was changed.

Solution 6 - Docker

If you know container ID or name (even stopped container), you can quickly dump file list on-the-fly.

$ docker export CONTAIN_ID_OR_NAME | tar tv
-rwxr-xr-x  0 0      0           0  2  6 21:22 .dockerenv
-rwxr-xr-x  0 0      0           0  2  6 21:22 .dockerinit
drwxr-xr-x  0 0      0           0 10 21 13:46 bin/
-rwxr-xr-x  0 0      0     1021112 10  8  2014 bin/bash
-rwxr-xr-x  0 0      0       31152 10 21  2013 bin/bunzip2
-rwxr-xr-x  0 0      0           0 10 21  2013 bin/bzcat link to bin/bunzip2
lrwxrwxrwx  0 0      0           0 10 21  2013 bin/bzcmp -> bzdiff
-rwxr-xr-x  0 0      0        2140 10 21  2013 bin/bzdiff
lrwxrwxrwx  0 0      0           0 10 21  2013 bin/bzegrep -> bzgrep
-rwxr-xr-x  0 0      0        4877 10 21  2013 bin/bzexe
......

Then you can save list to file and compare too list files.

If you insist to use image ID or name, you can dump first layer's file list on-the-fly:

$ docker save alpine |tar xO '*/layer.tar' | tar tv
drwxr-xr-x  0 0      0           0 12 27 06:32 bin/
lrwxrwxrwx  0 0      0           0 12 27 06:32 bin/ash -> /bin/busybox
lrwxrwxrwx  0 0      0           0 12 27 06:32 bin/base64 -> /bin/busybox
lrwxrwxrwx  0 0      0           0 12 27 06:32 bin/bbconfig -> /bin/busybox
-rwxr-xr-x  0 0      0      821408 10 27 01:15 bin/busybox

After all, i suggest you start the container then stop it, then you can get a merged file list as described in first way.

2017/02/01: The fastest way to show container's file list, you are free to enter its root dir to read files:

# PID=$(docker inspect -f '{{.State.Pid}}' CONTAIN_ID_OR_NAME)
# cd /proc/$PID/root && ls -lF
drwxr-xr-x  0 0      0           0 12 27 06:32 bin/
lrwxrwxrwx  0 0      0           0 12 27 06:32 bin/ash -> /bin/busybox
lrwxrwxrwx  0 0      0           0 12 27 06:32 bin/base64 -> /bin/busybox
lrwxrwxrwx  0 0      0           0 12 27 06:32 bin/bbconfig -> /bin/busybox
-rwxr-xr-x  0 0      0      821408 10 27 01:15 bin/busybox

Note, if you are using docker-machine, you need first enter it by docker-machine ssh then sudo sh.

Now you get the root dir of the two container, you can use diff to compare them directly.

Solution 7 - Docker

Have a look at:

https://github.com/moul/docker-diff

They list Brew install instructions for Mac, I'm assuming it's a Bash script, so I assume it could be made to work in other *nix environments.

Solution 8 - Docker

It sounds like in this case maybe you only needed to see the diff between two layers. If so, dive is awesome for this; it lets you inspect the filesystem at each layer and you can filter files by change type (unchanged, added, removed, modified).

And if you want to inspect the differences between two unrelated images, having two dive processes running side by side works okay too.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionjd.View Question on Stackoverflow
Solution 1 - Dockeraaron-prindleView Answer on Stackoverflow
Solution 2 - Dockerfallens4eView Answer on Stackoverflow
Solution 3 - DockerjerngView Answer on Stackoverflow
Solution 4 - DockertikaelView Answer on Stackoverflow
Solution 5 - DockerJohannes 'fish' ZiemkeView Answer on Stackoverflow
Solution 6 - Dockerosexp2003View Answer on Stackoverflow
Solution 7 - DockerBig RichView Answer on Stackoverflow
Solution 8 - DockeresmailView Answer on Stackoverflow