Configuring Docker containers

Deploying all of our new applications as containers.

As readers of our blog know we’ve been avid users of Docker since, well, almost since it exists and have been adopting CoreOS for some of our production workloads for many months now. In 2015 we’ll continue to closely follow the new developments (e.g. the new container runtime announced by CoreOS: Rocket) around the pattern we’ve adopted this year: deploying all of our new applications as containers.

Most of our apps follow the twelve-factor app manifesto and are configurable through environment variables alone. But there is also a plethora of legacy apps (like e.g. the member of the Atlassian toolchain family) and for them and every app caught in any state between those two philosophies we needed a solution to rewrite configuration files based on the value of certain environment variables.

Enter envplate

There are a few solutions for doing that, and in the past we’ve always favored the most simple: a wrapper script written in shell using sed -i to rewrite configuration files and calling exec to become the container process in the end.

Other solutions we’ve looked at include confd (which does a lot of things e.g. integrating with etcd or consul as well as adding real templating into the mix) and tiller (also adds external datasources, requires a Ruby VM to run). We always thought these solutions were doing either too much (and thus requiring us to adapt our software to them, not the other way around) or requiring dependencies we did not always want (like Ruby).

Our take on a solution for this problem - envplate (ep) - is a simpler thing.

  • it’s written in Go and released using Github releases - that means you do not need extra dependencies and you can download it directly from inside your Docker image build
  • it resolves one or many globs matching one or many configuration files and resolves references to environment variables - if it can’t find any files matching the glob of cannot find a defined key for a reference it fails with a sensible error message
  • the only magic ep performs is the ability to fallback to defaults, but even this behaviour can be disabled
  • after performing the reference substitutions, ep can optionally exec your application - for us this means no more wrapper scripts

Integrating ep into your Docker build can look as easy as this:

RUN curl -sLo /usr/local/bin/ep https://github.com/kreuzwerker/envplate/releases/download/v0.0.4/ep-linux && chmod +x /usr/local/bin/ep

...

CMD [ "/usr/local/bin/ep", "-v", "/etc/nginx/nginx.conf", "--", "/usr/sbin/nginx", "-c", "/etc/nginx/conf" ]

Hope you like it!