Docker is not a packaging tool — part 1

Posted by Jesse Portnoy on April 18, 2023 · 1 mins read

This is the second part of the series so, if you landed here, you should go back to the first segment where I gave a short intro and some arguments to solidify my basic stance (to wit: that Docker is not a packaging tool).

So then, where were we? Right, in the last episode, I promised to tell you about the challenge of delivering software to multiple UNIX and Linux distributions (same same but different) and how chroot was leveraged towards this objective…

The challenges

As I was saying, the product had to run on basically anything that has uname deployed on it and consisted of many different components written in C/C++, which in turn, depended on third party FOSS components, also written in C/C++.

The first thing you need to be able to do is build these components in a clean ENV.

If you’ve engaged in building and packaging software in a serious manner, that bit would be obvious to you but for the benefit of those who haven’t — this process taints the FS by definition.
Why? because anything that’s more than a very basic “hello world” like project has build and run-time dependencies and, in many (this is my cautious nature, the word to use is MOST) cases, of very specific versions.

Now, if you’re building loads of different components, chances are they will share some common dependencies but, and here’s the kicker, the versions will vary.

Typically, on a UNIX system (reminder: that includes Linux as well), versioning of shared libraries is handled thusly:

  • The version of an SO (Shared Object) will be reflected in its name, say:

  • A symlink called lib$ will be created, pointing to the actual SO; like this: ->

Sometimes, the symlink will also include the major version, i.e:

/lib/x86_64-linux-gnu/ ->

This allows for some co-existence of versions but is not enough to guarantee a reliable build process. Moreover, sometimes, you want to produce statically linked binaries, in which case, you’ll want to link against archives, rather than SOs and these typically do not reflect the version in their names at all; they are simply called $NAME.a (for example: libevent.a).

So that’s one reason why you need to start with a clean ENV each time but — it’s not the only one.

Read part II of this series to learn how pkg-config attempts to address some of these issues, what other problems one has to tackle in the pursuit of a solid build process, why proper packaging greatly improves matters, how utilising chroots made things far easier, why Docker was the next evolutionary step and, lastly— why, while grand, it is not an all encompassing, magic-holly-grail solution to all learnyour build and deployment headaches.