I’ll be totally honest in saying even though the Dockerfile is the supported way to build docker images, I have not quite bought into building my containers using the format. I believe the main thing we are losing with them is a platform agnostic tool to build machine images, which is useful if you don’t always want or need to use the container format but want to keep the same configuration across different types of hosts or environments. Defining infrastructure in code so that we can use logic, templates, and reusable patterns gives us so many more opportunities towards writing intelligent provisioning processes that span across development and production. Given that, I’ve turned to Chef as a tool which can represent my configuration at both the application and machine level.
My original use case was to spin up a Docker container to host our development environment, and then bring this same configuration into production. I’ve recently inherited an environment that didn’t use the concept of containers or really have any reproducible method to spin up new hosts. And even though this is basically what docker does best, we weren’t quite ready to mix containers into production when we were still trying to solidify the ground that it stands on and make small, careful improvements. So the idea was to use chef to provision docker containers for development of the application but also for testing chef itself, and then use those same recipes to build EC2 instances to stand up alongside the current system. The great thing about this is that we are able to run any chef recipe on a container, and test changes before moving them into production.
This chef container provisioning recipe is pretty straightforward and can be run with chef solo (for example, to easily provision a development instance on a laptop):
This gives us a container with the home directory mounted as a volume with correct user permissions, running a role we have defined as Dev containing several recipes. These same exact recipes might be put in a Prod role which is used in production. It doesn’t really matter if production is a container, EC2 instance, or something else like a bare metal server. Using this pattern can lay the groundwork to creating platform agnostic images for our infrastructure that are identical in configuration.