Docker Images Diff'ed

After I announced my Devuan Docker Images, Jaromil suggested that I'd run some kind of (binary) comparison on the images. I said I would but have taken my time getting around to doing so. Better late than never, so here you have it.

Size Matters

The Docker community is slightly obsessed with size. Smaller is considered better. So I compared my Devuan base images with their closest Debian counterparts in terms of download (compressed) and on-disk size.

Devuan Debian
Tag Compressed On Disk Compressed On Disk Tag
jessie-2017-12-12 39.93 MiB 91.11 MiB 53MB 117.67 MiB jessie-20171210
ascii-2017-12-12 41.76 MiB 92.49 MiB 45MB 95.44 MiB stretch-20171210
beowulf-2017-12-12 N/A N/A 48MB 100.58 MiB buster-20171210
ceres-2017-12-12 44.52 MiB 97.07 MiB 48MB 100.77 MiB sid-20171210

For the slim variants the picture is as follows

Devuan Debian
Tag Compressed On Disk Compressed On Disk Tag
jessie-2017-12-12 20.35 MiB 52.01 MiB 30MB 75.45 MiB jessie-slim
ascii-2017-12-12 21.35 MiB 52.43 MiB 22MB 52.68 MiB stretch-slim
beowulf-2017-12-12 N/A N/A 25MB 58.93 MiB buster-slim
ceres-2017-12-12 23.74 MiB 58.12 MiB 25MB 58.96 MiB sid-slim

From the above, I think it's fair to say that the Debian jessie images are a bit of a hog and that stretch and later have cleaned up their act. More on that later. The Devuan images for jessie are a good deal smaller. For the other tags they are a bit smaller than their Debian cousins but not much. The download size differences may just be the difference between Mebibytes (2^20 bytes) and Megabytes (10^6 bytes). What's really different between these images? Well, let's find out!

Comparing Against Upstream

Jaromil's post contained a link to a Linux Weekly News article about Google's container-diff. That looked interesting and just right for the kind of information I was after, so I gave it a spin. Since I had already pulled all the relevant Docker images to my local cache I used

container-diff diff --type apt --type file \
    daemon://debian:jessie-20171210 \

and similar to make comparisons based on packages installed and the files they contain. I didn't bother with --type history because all images just have a history of a single ADD instruction with a file that is guaranteed to be different (as a simple docker history --no-trunc $image will confirm).

The output shows what has been added with respect to the first image, what has been removed in the second image and lists what is different between the two. It does this for each --type given. The output is rather bulky so here is a sample limited to the Apt section.


Packages found only in debian:jessie-20171210:
NAME                       VERSION                      SIZE
-acl                       2.2.52-2                     258K
-adduser                   3.113 nmu3                   1M
-dmsetup                   2:1.02.90-2.2 deb8u1         123K
-inetutils-ping            2:           307K
-iproute2                  3.16.0-2                     1.1M
-libcap2                   1:2.24-8                     61K
-libcap2-bin               1:2.24-8                     110K
-libcryptsetup4            2:1.6.6-5                    227K
-libdevmapper1.02.1        2:1.02.90-2.2 deb8u1         330K
-libgcrypt20               1.6.3-2 deb8u4               998K
-libgpg-error0             1.17-3                       444K
-libkmod2                  18-3                         134K
-libncursesw5              5.9 20140913-1+deb8u2        353K
-libprocps3                2:3.3.9-9                    132K
-libsystemd0               215-17 deb8u7                183K
-libudev1                  215-17 deb8u7                101K
-netbase                   5.3                          66K
-procps                    2:3.3.9-9                    670K
-systemd                   215-17 deb8u7                11.2M
-systemd-sysv              215-17 deb8u7                40K
-udev                      215-17 deb8u7                5.8M

Packages found only in
NAME                   VERSION                     SIZE
-devuan-keyring        2017.10.03                  64K
-libfdisk1             2.26.2-6 devuan1            458K
-sysvinit-core         2.88dsf-59.2 devuan2        238K

Version differences:
PACKAGE                IMAGE1 (debian:jessie-20171210)        IMAGE2 (
-base-files            8 deb8u10, 413K                        8 devuan7, 447K
-bsdutils              1:2.25.2-6, 181K                       1:2.26.2-6 devuan1, 240K
-init                  1.22, 29K                              1.24 devuan1.0, 30K
-initscripts           2.88dsf-59, 165K                       2.88dsf-59.2 devuan2, 260K
-libblkid1             2.25.2-6, 326K                         2.26.2-6 devuan1, 371K
-libmount1             2.25.2-6, 357K                         2.26.2-6 devuan1, 402K
-libsmartcols1         2.25.2-6, 209K                         2.26.2-6 devuan1, 246K
-libuuid1              2.25.2-6, 89K                          2.26.2-6 devuan1, 122K
-lsb-base              4.1 Debian13+nmu1, 72K                 4.1 devuan2, 72K
-mount                 2.25.2-6, 357K                         2.26.2-6 devuan1, 430K
-sysv-rc               2.88dsf-59, 125K                       2.88dsf-59.2 devuan2, 223K
-sysvinit-utils        2.88dsf-59, 147K                       2.88dsf-59.2 devuan2, 149K
-util-linux            2.25.2-6, 2.7M                         2.26.2-6 devuan1, 4.7M

You can reproduce the results yourself by replacing the daemon:// prefix by remote:// (and assuming the relevant versions are still available). The container-diff utility stores retrieved images below $HOME/.container-diff/cache/ so you may want to reclaim some disk space by running

rm $HOME/.container-diff/cache/*

once you're done.


The details are available in jessie-jessie.txt, but comparing Debian's jessie with Devuan's jessie it is immediately clear that the main difference is the absence of systemd (and udev) in the latter. This is of course no big surprise as Devuan set out to remove systemd as the default init system. With the notable exception of iproute2 (which is added to the list of packages for debootstrap to install!) and some smaller network related packages, all of the other package removals are systemd and/or udev dependencies.

The fact that Devuan's jessie installs an init package doesn't really make a dent in the size difference but more on this later.


In this case the difference is a lot smaller. For one thing, systemd (and udev) have disappeared from Debian's stretch image. They don't show up anymore as a difference between the images. The image differences are mostly limited to iproute2 and libsystemd0 being installed only in stretch. The init and libeudev1 (bound to replace libudev1 in the long run) packages are only present in ascii. Nothing particularly interesting or it must be the absence of a libsystemd0 package in ascii.

The full output of the comparsion is in stretch-ascii.txt.


This is mostly a repeat of the previous section, with the exception of libeudev1 not being in ceres. It looks like that package has not made it into ceres yet and was "shoe horned" into ascii.

The full output of the comparsion is in sid-ceres.txt.

Upstream Got Smart, So Should We

We should keep in mind that Docker containers have no real need for an init system. Containers are normally supposed to run a single process. For those containers where something "init system"-like is required, tini is or used to be a fairly popular choice. It has been integrated into Docker as of 1.13 and is now available via the --init option to docker run.

It appears that the Debian developers realized that as well and dropped it from their images starting with stretch. Seeing that the Devuan images still contain an init package, I guess there is some work to be done.