Fight Docker Package Drift!

The Problem

While Dockerfiles can help enormously with pinning down the details of your build process, you can still fall victim to package drift. This is when package management changes behind the scenes, leaving you with nasty surprises to unpick.

You can specify the versions of your apt packages like this:

apt-get install package=version

but what about that package’s dependencies? And their dependencies? And so on…

“Solution”

The following command installs the given package you’re concerned with, and then spits out a Dockerfile RUN instruction with the specific versions used as dependencies. You can then place this into your Dockerfile, and if the build fails in the future, you’ll know something has changed.

The following example does this for vim, but you can change that package to whatever you like.

$ docker run imiell/get-versions vim RUN apt-get install -y vim=2:7.4.052-1ubuntu3 vim-common=2:7.4.052-1ubuntu3 vim-runtime=2:7.4.052-1ubuntu3 libacl1:amd64=2.2.52-1 libc6:amd64=2.19-0ubuntu6.5 libc6:amd64=2.19-0ubuntu6.5 libgpm2:amd64=1.20.4-6.1 libpython2.7:amd64=2.7.6-8 libselinux1:amd64=2.2.2-1ubuntu0.1 libselinux1:amd64=2.2.2-1ubuntu0.1 libtinfo5:amd64=5.9+20140118-1ubuntu1 libattr1:amd64=1:2.4.47-1ubuntu1 libgcc1:amd64=1:4.9.1-0ubuntu1 libgcc1:amd64=1:4.9.1-0ubuntu1 libpython2.7-stdlib:amd64=2.7.6-8 zlib1g:amd64=1:1.2.8.dfsg-1ubuntu1 libpcre3:amd64=1:8.31-2ubuntu2 gcc-4.9-base:amd64=4.9.1-0ubuntu1 gcc-4.9-base:amd64=4.9.1-0ubuntu1 libpython2.7-minimal:amd64=2.7.6-8 mime-support=3.54ubuntu1.1 mime-support=3.54ubuntu1.1 libbz2-1.0:amd64=1.0.6-5 libdb5.3:amd64=5.3.28-3ubuntu3 libexpat1:amd64=2.1.0-4ubuntu1 libffi6:amd64=3.1~rc1+r3.0.13-12 libncursesw5:amd64=5.9+20140118-1ubuntu1 libreadline6:amd64=6.3-4ubuntu2 libsqlite3-0:amd64=3.8.2-1ubuntu2 libssl1.0.0:amd64=1.0.1f-1ubuntu2.8 libssl1.0.0:amd64=1.0.1f-1ubuntu2.8 readline-common=6.3-4ubuntu2 debconf=1.5.51ubuntu2 dpkg=1.17.5ubuntu5.3 dpkg=1.17.5ubuntu5.3 libnewt0.52:amd64=0.52.15-2ubuntu5 libslang2:amd64=2.2.4-15ubuntu1 vim=2:7.4.052-1ubuntu3

Take that RUN line that was output, and place in your Dockerfile, eg where you had

FROM ubuntu:14.04 RUN apt-get update && apt-get install -y vim

you would now have:

FROM ubuntu:14.04 RUN apt-get update && apt-get install -y vim=2:7.4.052-1ubuntu3 vim-common=2:7.4.052-1ubuntu3 vim-runtime=2:7.4.052-1ubuntu3 libacl1:amd64=2.2.52-1 libc6:amd64=2.19-0ubuntu6.5 libc6:amd64=2.19-0ubuntu6.5 libgpm2:amd64=1.20.4-6.1 [...]

If you try and rebuild this and something has changed, you’re far more likely to catch and identify it early. This should be particularly useful for those paranoid about any kind of changes to their builds. It won’t solve all Docker “build drift” problems, but it is a start.

Source

The source code for this is available here.

Note that this assumes a debian flavour of ubuntu:14.04. If you have a different base image, fork the repo and change the Dockerfile accordingly. Then, from the same directory:

$ docker build -t get-versions . $ docker run get-versions vim

Help Wanted!

There are, I’m sure, plenty of improvements that could be made – maybe even scripts already in existence – to make this more robust and useful.

I’d also like to know if anyone can do this with other package managers.

If you have any ideas, do let me know: ian.miell@gmail.com