When you think of a configuration-defined image builder, most likely you think of Docker (which builds images for containers). But before Docker, there were several other projects, all of which came out of a vibrant community of Debian-using sysadmins looking for better ways to build VM and container images, which lead to a series of projects that built off each other to build something better.
Before KVM, there was Xen
The Xen hypervisor is likely something you’ve heard of, and that’s where this story begins. The mainstream desire to programmatically create OS images came about as Xen became a popular hypervisor in the mid 2000s. The first development in that regard was xen-tools, which automated installation of Debian, Ubuntu and CentOS guests, by generating images for them using custom perl scripts. The world has largely moved on from Xen, but it still sees wide use.
ApplianceKit and ApplianceKit-NG
The methods used in xen-tools, while generally effective, lacked flexibility. Hosting providers needed a way to allow end-users to customize the images they deployed. In my case, we solved this by creating ApplianceKit. That particular venture was sold to another hosting company, and for whatever reason, I started another one. In that venture, we created ApplianceKit-NG.
ApplianceKit and ApplianceKit-NG took different approaches internally to solve a basic problem, taking an XML description of a software image and reproducing it, for example:
<?xml version="1.0" standalone="yes"?> <appliance> <description>LAMP appliance based on Debian squeeze</description> <author> <name>Ariadne Conill</name> <email>firstname.lastname@example.org</email> </author> <distribution>squeeze</distribution> <packagelist> <package>apache2</package> <package>libapache2-mod-php5</package> <package>mysql-server</package> <package>mysql-client</package> </packagelist> </appliance>
As you can see here, the XML description described a desired state for the image to be in at deployment time. ApplianceKit did this through an actor model: different modules would act on elements in the configuration description. ApplianceKit-NG instead treated this as a matter of compilation: first, a high-level pass converted the XML into a mid-level IR, then the mid-level IR was converted into a low-level IR, then the IR was converted into a series of commands that were evaluated like a shell script. (Had I known about skarnet’s execline at that time, I would have used it.)
Another company that was active in the Debian community and experimenting with configuration-defined image building was dotCloud. dotCloud took a similar evolutionary path, with the final image building system they made being Docker. Docker evolved further on the concept outlined in ApplianceKit-NG by simplifying everything: instead of explicitly configuring a desired state, you simply use image layering:
FROM debian:squeeze MAINTAINER email@example.com RUN apt-get update && apt-get install apache2 libapache2-mod-php5 mysql-server mysql-client
By taking a simpler approach, Docker has won out. Everything is built on top of Docker these days, such as Kubernetes, and this is a good thing. Even though some projects like Packer have further advanced the state of the art, Docker remains the go-to for this task, simply because its simple enough for people to mostly understand.
The main takeaway is that simply advancing the state of the art is not good enough to make a project compelling. It must advance the state of simplicity too.