There is a need for shims like confd, though perhaps we'll see configuration information libraries emerge that can go straight to a service discovery/config lookup endpoint such as etcd or zookeeper.
All of the config management tools have some sort of overhead and all affect the ability for a container (bar its data in the case of databases) to be immutable.
Building the container should be as simple as installing the package for the given app into whatever container systems is being used, be it Docker, a more bare bones container, or something that comes from the standarisation effort.
The base 'OS' in the container then becomes irrelevant, as the base OS is really the containing, host OS, with the containers just containing the apps and not additional overhead.
In terms of where configuration management fits, it potentially is at the orchestration level, but that said there are already other, more specialised tools emerging in that space too.
In addition -- I'd consider the "rerun the config tool on a pre-existing container" to be an anti-pattern. This creates more and more layers to the Docker file that have to be downloaded every time that container is run. I'd much rather build each container from a bedrock up with well versioned dependencies (not as easy as it should be with many package managers).
I fully agree that "rerun the config tool on a pre-existing container" is an anti-pattern, and it's best to avoid it if at all possible. I can see how what you are proposing would be a great step in a positive direction.
I'm not convinced CM systems don't have a role, still. They are very flexible and powerful at accommodating many specialized system setup scenarios. But I think that's independent of what you're really focused on here.
Anyway, excellent and well-written article!
1) Run a base docker image.
2) Run the config management tool on/in this image, (ansible playbook, chef cookbook, etc.)
3) Commit the container to the new image
Dockerfiles are very convenient and easy, and are great as far as they go. They also don't have idempotent actions built-in. As a result, a minor change requires one to rebuild the entire image from scratch.
In contrast, the CM systems mentioned above operate by letting you declare the desired system state - i.e., what it is, instead of how to create it. This lets the CM system runtime automatically skip unnecessary steps. For example, in (say) an Ansible playbook, instead of (in the Dockerfile):
... we'd say something like (in the Ansible playbook): If /path/to/some/dir already exists, and I run this play twice, I do not get the "mkdir: cannot create directory ‘/path/to/some/dir’: File exists" error, because this is designed to be declarative. That means: Ansible first checks whether the directory exists, and if it does, it does nothing. If it doesn't, it recreates it.It also helps a lot with surgical updates. For example, suppose my Dockerfile for a web service container contains the following:
An analogous Ansible play might include the following: Now if an Apache security vulnerability is announced, with a fix pushed to the apt sources, I can rapidly modify the image like so:1) Run the previous docker image.
2) Run the config management tool with the surgical-update action.
3) Commit the container to create an updated image.
The Ansible version of the update would be as simple as:
And again, this is a fast no-op if the package is already up-to-date. (It also doesn't needlessly restart apache, though when creating an image that doesn't matter much.)Using a CM system like this doesn't solve all the problems outlined in the article - actually, I don't think it even solves a majority of them. But I can't figure out why so many smart people are focused on reinventing parts of it poorly, or thinking in terms of "docker vs. ansible/chef/puppet/salt". I know they're not idiots. Am I missing something? If so I'd sincerely like to know.