Docker is very cool to create lightweight hosts to your micro/macro services in a repeatable way.
The problem with using docker is that the machine configuration is not decoupled from docker itself, so you will be stuck with docker to setup your infrastructure.
How cool it would be to use ansible and docker together in order to:
- isolate machine configuration
- use docker and easily replicate environments
This article will show you how to create an empty centos 7 docker container within docker-machine and use ansible to do the machine setup.
By doing this you can use share machine configuration tasks between projects, keeping your entire infrastructure updated. Imagine that!
A ready to run example is available at example-ansible-docker-connection.
dynamic inventory
Because docker runs on top of a linux kernel, a docker-machine virtual machine is used to host docker on OSX and Windows machines.
This configuration is transparent to the docker client, after an eval "$(docker-machine env local)"
, which sets up some connection environment variables that the docker
client needs.
We'll need this docker-machine information on our ansible playbooks in order to call docker. This is done using a dynamic inventory
which, in this case, is a python script that evaluates our current environment variables.
playbook
Now that we have the docker host information we can write an ansible playbook to startup a docker and use ansible to install some packages within the newly created docker container.
---
# run an empty centos 7 container
- hosts: docker-host
vars:
# workaround error "docker-py is needed for this module"
ansible_python_interpreter: "/usr/bin/env python"
tasks:
- name: build docker image
docker:
image: "centos:7"
name: "divhide-test"
state: "reloaded"
docker_url: "{{ docker_host_url }}"
use_tls: "encrypt"
command: sleep 5m
environment:
DOCKER_CERT_PATH: "{{ docker_host_cert_path }}"
# register the running container
register: docker_result
- name: add new docker connection {{ docker_result.ansible_facts.docker_containers[0].Config.Hostname }} to docker-container inventory group
add_host:
name: "{{ docker_result.ansible_facts.docker_containers[0].Config.Hostname }}"
groups: "docker-container"
ansible_connection: docker
ansible_ssh_user: "root"
ansible_become_user: "root"
ansible_become: "yes"
# setup the new machine using ansible instead of docker
- hosts: docker-container
tasks:
- name: install vi
yum:
name: vi
state: present
Note that this playbook is dynamically adding a new host to the docker-container
group using a docker connection
instead of using SSH.
how to run
Let's get busy then. To run this example you simply have to do the following.
# download the example
git clone https://github.com/divhide/example-ansible-docker-connection.git
# start your docker-machine virtual machine
docker-machine start local
eval "$(docker-machine env local)"
# run the playbook using the dynamic inventory
ansible-playbook -i docker-machine.py playbook.yml
We have now a docker container running and configured with ansible.
summary
This is just a simple example of a machine configuration playbook that can be easily changed to point to another type of hosting other than docker.
Downsides? Problems? Share your thoughts by commenting.
Oscar out