
Docker the Ansible Way
Orchestrating Docker Containers with Ansible
Ansible is powerful tool that does orchestration, including orchestrating Docker containers through a simple its own DSL (domain specific language) represented in YAML file format.
Under the hood, the docker modules in Ansible use the Docker SDK for Python to make this magic happens, so this library must be installed on the target system to use the modules.
For this exercise, like similar articles, we will use Ansible to orchestrate WordPress and dependent MySQL 5.7 database.
I will introduce the problem and tools needed to bring this up, even tests to verify the solution is working, and in a follow-up article, present the solution.
Related Articles
Problem Requirements for Docker Command
Solution in Shell Script for Docker Command
Prerequisites
You need to have at minimum Docker installed, Python environment installed, and these python packages:
- Docker Library: https://pypi.org/project/docker/
- Ansible Tool: https://pypi.org/project/ansible/
Make sure that you are using at least Ansible 2.8 or higher. The final solution requires a minimum version of Ansible 2.2.
Article on Python Environments using PyEnv
This is an earlier article about managing Python versions using pyenv
tool. This may be useful for setting up initial environment needed for docker
and ansible
python modules.
The Problem
The goal of this project is to launch two containers (WordPress and MySQL) on a private network, with persistent database, and accessible by a user specified port through WORDPRESS_PORT
. Create an Ansible playbook, docker_run.yml,
to the following listed below.
I’ll divide the requirements into two parts.
Basic Container Features
- Launch MySQL (
mysql:5.7
) with restart policy ofalways
, use friendly container name ofdb
, and configure the root password as well as database and user so that Wordpress app can use it (hint: pass env vars to container) - Launch WordPress (
wordpress:latest
) with port map from container web port80
to host port of8080
, restart policy ofalways
, use friendly container name ofwordpress
, and configure the container to use the MySQL database (hint: pass env vars to container)

Advanced Container Features
We want to create and support network and volume resources, and allow the user to specify the host port.
- For the WordPress (
wordpress:latest
), map the host port to a port specified by the user with theWORDPRESS_PORT
environment variable (hint: Jinja2); if this is not set, default it to8080
(hint: Jinja2 filter). - For both containers, use a private network
wordpress_net
. - For the MySQL (
mysql:5.7
), use a persistent volume calleddb_data
, and use this for the MySQL database.

Formal Requirements Document
Starter Script
I created this started script to get you started:
You can download this as docker_run.yml, then run:
ansible-playbook docker_run.yml
You will need to create the tasks as well as code to fetch the environment variable WORDPRESS_PORT
, and set it to a default if the environment variable WORDPRESS_PORT
is not set.
The Verification
When you are finish, try your script using both the default port 8080, and a port of your choosing that is specified by the WORDPRESS_PORT
.
Some Testing Is Just Not Needed
Any competent change configuration should be idempotent when configuring resources like docker volumes, networks, and containers. Thus, you do not need to code in behavior to check if you should not create things that exist, or code necessary checks that can cause an error. The docker modules in Ansible should handle such conditions.
Automated Validation
I wrote a script that can be used to valid the final solution, so you can apply TDD (Test Driven Design) to validate your final solution. You will need InSpec 3.x installed for this to work. If you install InSpec 4.x using Ruby gem install
, you will need the inspec-bin
in addition to inspec
gems.
To run the script above, just download and type:
ansible-playbook docker_run.yml
inspec exec container_test.rb
For testing different ports, you can do the following:
export WORDPRESS_PORT=8888
ansible-playbook docker_run.ymlecho "port: $WORDPRESS_PORT" > attributes.yml
inspec exec container_test.rb
Resources
Here are some links related to the exact modules you would utilize for this exercise:
docker_volume
: https://docs.ansible.com/ansible/latest/modules/docker_volume_module.htmldocker_network
: https://docs.ansible.com/ansible/latest/modules/docker_network_module.htmldocker_container
: https://docs.ansible.com/ansible/latest/modules/docker_container_module.html
Wrapping Up
In this article, I only wanted to present the problem, and I will follow-up with the solution.
I hope you can try the validation script with InSpec, to get used to TDD style of programming. It’s useful, especially in tutorials and training.
In the future, I may also create a TestInfra equivalent, but if anyone wants develop one, such a contribution would be welcomed, I could add it to this article.