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


You need to have at minimum Docker installed, Python environment installed, and these python packages:

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

  1. Launch MySQL (mysql:5.7) with restart policy of always, use friendly container name of db, and configure the root password as well as database and user so that Wordpress app can use it (hint: pass env vars to container)
  2. Launch WordPress (wordpress:latest) with port map from container web port 80 to host port of 8080, restart policy of always, use friendly container name of wordpress, 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.

  1. For the WordPress (wordpress:latest), map the host port to a port specified by the user with the WORDPRESS_PORT environment variable (hint: Jinja2); if this is not set, default it to 8080 (hint: Jinja2 filter).
  2. For both containers, use a private network wordpress_net.
  3. For the MySQL (mysql:5.7), use a persistent volume called db_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
exec container_test.rb

For testing different ports, you can do the following:

export WORDPRESS_PORT=8888
ansible-playbook docker_run.yml
echo "port: $WORDPRESS_PORT" > attributes.yml
inspec exec container_test.rb


Here are some links related to the exact modules you would utilize for this exercise:

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.

Linux NinjaPants Automation Engineering Mutant — exploring DevOps, o11y, k8s, progressive deployment (ci/cd), cloud native infra, infra as code

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Connect to Cassandra with Python 3.x and get Pandas Dataframe

Kubernets Inc Tech Bootcamp

FANATEC Formula V2 Clicking noise from Quick Release Vanished

Double-A Chain | Weekly Report №202(2022.2.28–2022.3.6)

What does Google Cloud’s Outage Signify?

How I built webdesignrepo in 17 days with JAMstack

A better human (topic)


Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Joaquín Menchaca (智裕)

Joaquín Menchaca (智裕)

Linux NinjaPants Automation Engineering Mutant — exploring DevOps, o11y, k8s, progressive deployment (ci/cd), cloud native infra, infra as code

More from Medium

Running Ansible from Gitlab CI

Deploy Apache Web Server in a Docker Container for Debian-like systems

Connect to an Azure VM via RDP on Linux using Remmina

Installing a LAMP Stack on Azure VM