Andre
Andre

Reputation: 1322

How to test Ansible playbook using Docker

I'm new to ansible (and docker). I would like to test my ansible playbook before using it on any staging/production servers.

Since I don't have access to an empty remote server, I thought the easiest way to test would be to use Docker container and then just run my playbook with the Docker container as the host.

I have a basic DockerFile that creates a standard ubuntu container. How would I configure the ansible hosts in order to run it against the docker container? Also, I suspect I would need to "run" the docker container to allow ansible to connect to it.

Upvotes: 27

Views: 21458

Answers (4)

Ewa
Ewa

Reputation: 593

Apart from provisioning localhost (the machine where you have Ansible installed), you can also tell Ansible to:

  1. create a new docker container,
  2. provision that container,
  3. destroy that container.

For this to work you need such a hosts.yaml file:

all:
  hosts:
    mycontainer:
      ansible_connection: docker
    localhost:
      ansible_connection: local

such a playbook.yaml file:

---
- name: Create a container to be provisioned later
  hosts: localhost
  tasks:
    - name: create docker container
      docker_container:
        name: mycontainer
        image: python:2.7.16-slim-stretch
        command: ["sleep", "1d"]

- name: Provision the container created above
  hosts: mycontainer
  roles:
    - simple

and another playbook file: destroy.yaml used to destroy the container:

---
- name: Destroy a container
  hosts: localhost
  tasks:
    - name: destroy docker container
      docker_container:
        name: mycontainer
        state: absent

Create also a simple role: roles/simple/taksks/main.yaml

---
- name: Create a file
  copy:
    content: "hi!!"
    dest: /tmp/hello
    force: yes
    mode: 0555

And now to create a container and provision it, run:

ansible-playbook -i ./hosts.yaml ./playbook.yml

Verify that container was provisioned (the file was created):

docker exec mycontainer cat /tmp/hello

To destroy the container run:

ansible-playbook -i ./hosts.yaml ./destroy.yml

There are of course disadvantages:

  • the container must have python installed
  • some Ansible modules might not work, because additional python packages have to be installed. E.g. if you wanted to deploy docker containers (in the docker container), you have to install docker python SDK (pip3 install docker)

I was inspired by this blog post: https://medium.com/@andreilhicas/provision-docker-containers-with-ansible-30cc5ee6d950

Upvotes: 5

chrism
chrism

Reputation: 1661

I've created a role for this vary scenario: https://github.com/chrismeyersfsu/provision_docker. Easily start Docker containers and use them in your role or playbook, as inventory, to test.

Includes:

  • Curated Dockerfile for Ubuntu 12.04 & 14.04 as well as CentOS 6 & 7 that put back in the distro-removed init systems
  • start ssh

Also note the examples all have a .travis.yml file to form a CI pipeline using Travis CI.

Examples:

Upvotes: 4

William Yeh
William Yeh

Reputation: 719

There's a working example regarding this: https://github.com/William-Yeh/docker-ansible

First, choose the base image you'd like to begin with from the following list:

  • williamyeh/ansible:debian8-onbuild
  • williamyeh/ansible:debian7-onbuild
  • williamyeh/ansible:ubuntu14.04-onbuild
  • williamyeh/ansible:ubuntu12.04-onbuild
  • williamyeh/ansible:centos7-onbuild
  • williamyeh/ansible:centos6-onbuild

Second, put the following Dockerfile along with your playbook directory:

FROM williamyeh/ansible:ubuntu14.04-onbuild

# ==> Specify playbook filename;   default = "playbook.yml"
#ENV PLAYBOOK   playbook.yml

# ==> Specify inventory filename;  default = "/etc/ansible/hosts"
#ENV INVENTORY  inventory.ini

# ==> Executing Ansible...
RUN ansible-playbook-wrapper

Third, docker build .

For more advanced usage, the role in Ansible Galaxy williamyeh/nginx also demonstrates how to do a simple integration test for a variety of Linux distributions on Travis CI’s Ubuntu 12.04 worker instances.

Disclosure: I am the author of the docker-ansible and wiliamyeh/nginx projects.

Upvotes: 16

Ben Whaley
Ben Whaley

Reputation: 34406

Running the playbook in a docker container may not actually be the best approach unless your stage and production servers are also Docker containers. The Docker ubuntu image is stripped down and will have some differences from a full installation. A better option might be to run the playbook in an Ubuntu VM that matches your staging and production installations.

That said, in order to run the ansible playbook within the container you should write a Dockerfile that runs your playbook. Here's a sample Dockerfile:

 # Start with the ubuntu image
 FROM ubuntu
 # Update apt cache
 RUN apt-get -y update
 # Install ansible dependencies
 RUN apt-get install -y python-yaml python-jinja2 git
 # Clone ansible repo (could also add the ansible PPA and do an apt-get install instead)
 RUN git clone http://github.com/ansible/ansible.git /tmp/ansible

 # Set variables for ansible
 WORKDIR /tmp/ansible
 ENV PATH /tmp/ansible/bin:/sbin:/usr/sbin:/usr/bin
 ENV ANSIBLE_LIBRARY /tmp/ansible/library
 ENV PYTHONPATH /tmp/ansible/lib:$PYTHON_PATH

 # add playbooks to the image. This might be a git repo instead
 ADD playbooks/ /etc/ansible/
 ADD inventory /etc/ansible/hosts
 WORKDIR /etc/ansible

 # Run ansible using the site.yml playbook 
 RUN ansible-playbook /etc/ansible/site.yml -c local

The ansible inventory file would look like

[local]
localhost

Then you can just docker build . (where . is the root of the directory where your playbooks and Dockerfile live), then docker run on the resulting image.

Michael DeHaan, the CTO of Ansible, has an informative blog post on this topic.

Upvotes: 18

Related Questions