Configuring Docker Containers

There are two approaches to configuring a Docker container with Ansible:

  • CHROOT: configure a rootfs with the chroot connection plugin and import it in Docker
  • SSH: launch an ssh server in the container and use Ansible with the default SSH connection plugin

Each approach presents a drawback:

  • CHROOT: cannot save the state of the container in between runs of Ansible.
    This prevents Docker from sharing rootfs layers and therefore prevents caching.
  • SSH: requires an SSH server running in the container.
    This SSH server is not necessarily a desired service in the container.
    Furthermore, paying the SSH setup and encryption costs for a local container seems silly.

Wouldn’t it be nice to harvest the power of Docker rootfs sharing/caching with the following Dockerfile:

PLUGIN ansible
FROM ubuntu
RUN apt-get install python apt-python
ANSIBLE install-things.yaml
ANSIBLE setup-things.yaml
ANSIBLE run-things.yaml

If I understand Docker builds correctly, a RUN <command> directive work as follows:

  • Start the Docker container with rootfs available after the last line, and the command <command>.
  • Once <command> ends, the container stops and the rootfs is saved.

Implementing an Ansible directive seems to be doable, using the accelerate connection plugin without an SSH setup phase as follows:

  • Start the Docker container with the command python -c "<ansible accelerate daemon code>".
  • Use ansible-playbook with the accelerate-no-ssh connection plugin (to be implemented) to configure the container.
  • Once ansible-playbook is done, the daemon stops which stops the container, and the rootfs can be saved.

I have started a discussion regarding the Docker side of things at: https://github.com/dotcloud/docker/issues/2841. It also includes a little bit more of motivation of why I think Ansible and Docker are a good match.

Nicolas,

I’ve done something similar with my DockerDNA project: https://github.com/wrale/docker-dna

Thanks,
Joshua

I like the chroot idea a little better on principle.

What do you mean by “+ CHROOT: cannot save the state of the container in between runs of Ansible.”

Hi Josh,

Can you add in README.md how an end user would use that to build a container based on some helloworld.yml, etc?

referring to https://github.com/wrale/docker-dna/blob/master/README.md

I added to the DockerDNA Readme (https://github.com/wrale/docker-dna), though I haven’t had time to obsessively test every step.

A lot of what I ended up doing with DockerDNA owes to working within the constraints which Docker and its Dockerfile syntax imposes. For instance, I’d rather externalize the Dockerfile’s dependency on Ansible roles and such; meaning, I wanted to call out to an existing something.yml elsewhere in the filesystem.

Dockerfile ADD directives add files and directories to containers. However, the ADD only works on directories and files in or children to the directory where the Dockerfile is located. Symlinks, both hard and symbolic, work poorly if practically at all here, due to git limitations and Dockerfile limitations, respectively.

In effect, one must: (A) put the Dockerfile in an existing Ansible structure on the building host, or (B) put an Ansible structure where the Dockerfile is distributed via git. I chose (B), because it seemed more portable option.

I clicked through to the Docker issue Nicolas mentioned. One of the posters there, fgrehm, mentioned Packer as a resource which can build Docker images configured with Ansible. See: http://www.packer.io/docs/builders/docker.html

In light of this and my previous positive experiences with Packer (sans Docker, though plus Ansible), I believe a flexible Packer module for Ansible should be built. The new Packer module should have the ability to beautifully execute Ansible during Docker builds with minimal duplication of effort. (Not to mention, Packer on it’s own merit is an excellent tool in many ways.)

Perhaps at a later time, the Docker module could begin to transparently call the Packer module for easier builds, though this would complicate the package dependency chain.

I hope this is helpful.

Please let me know if you have any questions or comments.

Thanks,
Joshua