playing with Ansible container

2017-03-16 UPDATE - I’m not sure I see a good use case for Ansible container. It’s neat, but at this time it comes off as overly complicated and REALLY slow. Maybe it will advance and become interesting, but right now, a Dockerfile seems better in many ways.

Using ansible-container, the post covers creating Docker images, specifically images for development with AWS and Azure. It will configure the images accordingly, using Ansible playbooks and roles.

background

Managing Docker can be somewhat unweildy. Dockerfiles are essentially a giant bash script. Ansible-container can help with that and provide a way of managing that lifecycle.

This post walks through the installation of ansible-container and the creation of a few images and containers. In this example, their are two images, awsdev and azuredev. awsdev installs the necessary developer tools to work with AWS, and azuredev installs the necessary tools to work with Azure. They’re good for interactive examples. These containers are most useful when working from OS X development platforms and there is value in isolating those tools and environments. Can be a nicer setup than running full-blow VMs.

All steps are run from the ansible-container directory within the git project playbook, which can found here.

installing ansible-container

The first step is installing ansible-container, which has just hit 0.2.0. There are bugs, that comes with the territory of new software.

To install, simply run the environment.sh script here. This will:

  • If the Python virtual environment is not created, creates it.
  • Install the necessary Ansible tools via pip.
  • Installs ansible-container.

See the README.md for information.

a look at the ansible-container container.yml and main.yml

Ansible-container has an init command which will create the directory structure. Running this will create an ansible folder with container.yml, main.yml, and requirements.txt files. Pretty straightforward:

(env) % ansible-container init
Ansible Container initialized.
(env) % ls ansible/
ansible.cfg      container.yml    main.yml         requirements.txt requirements.yml
  • ansible.cfg is the Ansible configuration file. Standard Ansible fare.

  • The container.yml file is where the Docker image and container settings are defined. This is a Jinja templated file (as of 0.2!), which means we can use the same Ansible logic and variables. The best way to describe this file is directly from the docs themselves:

The container.yml file is very similar to the Docker Compose version 1 schema. Much like Docker Compose, this file describes the orchestration of your app. Ansible Container uses this file to determine what images to build, what containers to run and connect, and what images to push to your repository. Additionally, when Ansible Container generates an Ansible role to ship and orchestrate your images in the cloud, this file describes the configuration that role ensures is met.

As described, this is where the Docker orcestration can come into play. This is also where dev environments vs deployment environments can be configured. More information on container.yml can be found here. In the future, I would like to explore this more (see future improvements below). For now, the Docker URL and Docker namespace are the only variables set within this file.

  • main.yml is the Ansible playbook that configures the Docker containers. Each image within the container.yml file is added to the Ansible inventory. Adding it to the host list will have Ansible configure that Docker image much like it was a standard system being configured by Ansible.

  • requirements.txt is the Python requirements file for ansible-container.

  • requirements.yml is the Ansible yaml file that installs the necessary Ansible-galaxy roles. Something to dig into.

build an image with roles

Now that some of the basics First step, source the Python virtual env:

% cd /path/to/playbook/ansible-container
% ./environment.sh
% source ./env/bin/activate

Environment set. Running ansible-container version should reveal:

(env) % ansible-container version
Ansible Container, version 0.2.0

Using the 0.2.0 pre-release version, as it has some new notable features (the ability to use custom Ansible roles path being one of them).

To build the images from the git project:

cd devcontainers
ansible-container --debug build --with-volumes /full/path/to/playbook/ansible-roles:/roles

This will run the main.yml Ansible playbook against all Docker images/containers defined within container.yml. Each container defined is treated as part of the Ansible inventory and is added to the Ansible inventory. It will take a while; Hopefully because it’s a 0.2.0 version, it’s slow and this isn’t the final speed. You can leave out the --debug, at this point in ansible-container’s development cycle, it’s useful.

Note the ansible.cfg file. Note the path of the roles. This is actually the path WITHIN the ansible-container Docker image (ansible/ansible-container-builder), which gets volume mounted into the container.

Taking a look at the docker images, this is what gets created:

(env)% docker images
REPOSITORY                                                      TAG                 IMAGE ID            CREATED             SIZE
ansible-container-awsdev                                        20161008144935      8a10947917dc        32 minutes ago      1.006 GB
ansible-container-awsdev                                        latest              8a10947917dc        32 minutes ago      1.006 GB
ansible-container-azuredev                                      20161008144935      1236277b974c        32 minutes ago      973.6 MB
ansible-container-azuredev                                      latest              1236277b974c        32 minutes ago      973.6 MB
ansible/ansible-container-builder                               0.2                 6a0481cdff24        10 days ago         710.6 MB

run the container

ansible-container can run the container as well. This is far more useful when the container.yml is a bit more in depth and there’s actual intra-container orchestration needed. A future playbook will include something that can use this functionality.

push the images

When pushing, the variables docker_url and docker_namespace are needed. These are variables defined in container.yml. Note if a different repository is used, edit the file as needed. Push also requires the --with-volumes option, as Push uses the ansible-container inventory and loads the main.yml playbook:

ansible-container --debug push --with-volumes /full/path/to/playbook/ansible-roles:/roles --with-variables docker_url=https://YOUR.DOCKERREGISTRY.COM,docker_namespace=YOURNAMESPACE

Again, debug is useful to see any isuses that pop up. It is 0.2 software after all. After pushing, it will create another tag. Note the image list now:

(env)% docker images
REPOSITORY                                                      TAG                 IMAGE ID            CREATED             SIZE
ansible-container-awsdev                                        20161008144935      8a10947917dc        32 minutes ago      1.006 GB
ansible-container-awsdev                                        latest              8a10947917dc        32 minutes ago      1.006 GB
bcawthra/ansible-container-awsdev                               20161008144935      8a10947917dc        32 minutes ago      1.006 GB
ansible-container-azuredev                                      20161008144935      1236277b974c        32 minutes ago      973.6 MB
ansible-container-azuredev                                      latest              1236277b974c        32 minutes ago      973.6 MB
bcawthra/ansible-container-azuredev                             20161008144935      1236277b974c        32 minutes ago      973.6 MB
ansible-container-awsdev                                        20161008144710      545a9a293e09        34 minutes ago      937.5 MB
ansible-container-azuredev                                      20161008144710      bfbd10c20d36        34 minutes ago      904.8 MB
ansible/ansible-container-builder                               0.2                 6a0481cdff24        10 days ago         710.6 MB

conclusion

Interesting tool. Good for creating custom images using a known Ansible process, especially if there is invested knowledge in Ansible. When teamed up with Kubernetes, it can provide an excellent platform for deploying a stack both locally for development and to a Docker platform. I’m going to dig into some of these features in the future.

future improvements

  • Configure containers and images that build a stack of something, such as ELK, Prometheus/Alertmanager/Grafana, or some other multiple component tool.
  • Configure container.yml to support both a local development environment and some Docker platform (most likely Kubernetes).
  • Configure container.yml with additional Ansible/Jinja variables.

links