I’ve spent the past two days working on a way to improve Docker image generation, by using the C preprocessor to allow me to include Dockerfiles in other Dockerfiles. Part of this was to eliminate redundant typing, with the bonus that I’ve been able to code best-practice directly into the includeable Dockerfiles.
I’ve checked all this into this github repository — https://github.com/nuket/dockarchive — to keep track of things.
For example, let’s say you want to run an SSH server (sshd
) in a Docker container. One of the ways to do this is to use supervisord
, to start and to keep it running. So there’s an implicit dependency, which can be captured in the following way:
Dockerfile.supervisord
1
2
3
4
5
6
7
8
|
#ifndef DOCKERFILE_SUPERVISORD
#define DOCKERFILE_SUPERVISORD
#// Install supervisord.
RUN apt-get install -y supervisor
#endif // DOCKERFILE_SUPERVISORD
|
Dockerfile.ssh
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#ifndef DOCKERFILE_SSH
#define DOCKERFILE_SSH
#include "Dockerfile.supervisord"
RUN apt-get install -y ssh
RUN mkdir /var/run/sshd
RUN /bin/echo -e "[program:sshd] \ncommand=/usr/sbin/sshd -D \n" > /etc/supervisor/conf.d/sshd.conf
EXPOSE 22
#endif // DOCKERFILE_SSH
|
Dockerfile.supervisord.run
1
2
3
4
5
6
|
#ifndef DOCKERFILE_SUPERVISORD_RUN
#define DOCKERFILE_SUPERVISORD_RUN
CMD ["/usr/bin/supervisord", "-n"]
#endif // DOCKERFILE_SUPERVISORD_RUN
|
The sshd
installation can pull in its dependency and add a configuration to be automatically started by supervisord. Docker images can then be built up in an orderly way and complexity cut into smaller pieces, as each piece only needs to worry about its own particular configuration. In this way, the pieces can be combined into full images.
As an example, the source for one of my Docker images is very simple now, since the dependency tree is taken care of:
buildbot-master/Dockerfile.in
1
2
3
|
#include "baselines/Dockerfile.ubuntu1204"
#include "packages/Dockerfile.buildbot-master"
#include "packages/Dockerfile.supervisord.run"
|
Then you just use the C preprocessor to create the actual Dockerfile
and then build that:
1
2
|
cpp -I$HOME/dockarchive Dockerfile.in -o Dockerfile
docker build .
|