Docker the Terraform Way

Problem Challenge for Orchestrating Docker Containers with Terraform

Joaquín Menchaca (智裕)
4 min readMay 30, 2019

--

I create a series of articles that demonstrates how to orchestrate Docker in a variety of methods using Ansible, Docker Compose, or scripting languages. This article shows how to create do the same thing with Terraform.

About Terraform

Though some may not want to admit, but Terraform is essentially a change configuration and orchestration tool for resources exposed through a RESTful web interface. Terraform is popular with cloud infrastructure provisioning, using the web API from popular cloud providers like AWS, Google Cloud, and Azure.

On a system, as the Docker service (daemon) communicates through a web interface, it is a perfect candidate to automate through Terraform, and sure enough, there’s a Docker Provider.

Prerequisites

The tools needed for this are:

The Problem Challenge

For this problem, we want to orchestrate two Docker containers: WordPress and MySQL. These containers will always restart should they fail, the database will persist outside the life of the MySQL container, and the WordPress will be accessible through a user defined port, and will communicate to the database on a private network.

Below are details on what exactly to implement.

Basic Feature Requirements

We get started by just bringing up the containers.

Basic Features Table

For specifics, we want to do the following:

  1. Launch the MySQL 5.7 container (mysql:5.7) with restart policy of always, container name of db, and send environment variables to the container that will trigger the container’s internal automation to configure root password, wordpress user and password, and wordpress database.
  2. Launch the WordPress container (wordpress:latest) with restart policy of always, container name of wordpress, and send environment variables to the container that will trigger the container’s internal automation to configure hostname (db) and port (3306), and password to the wordpress database.

Advanced Feature Requirements

Now we can configure a private container network, persistent volume, and add support to changing the wordpress host or external port.

For specifics:

  1. Add support for wordpress_port input variable with a default of 8080. When using the terraform, we can set the variable to be equal to the WORDPRESS_PORT environment variable.
  2. Create a network called wordpress_net, and have both containers use this network by setting network_mode.
  3. Create a volume called db_data, and mount this volume as /var/lib/mysql on the db container.

Getting Started

Below is a script to get your started.

Download the script and then run terraform init do download and install the Docker Provider.

You can try out the Terraform script by running these commands:

terraform plan    # list changes needed
terraform apply # launch containers
terraform destroy # cleanup

When you are ready to try out wordpress_port input variable with WORDPRESS_PORT environment variables, you can do this:

export WORDPRESS_PORT=8888
terraform plan -var="wordpress_port=$WORDPRESS_PORT"
terraform apply -var="wordpress_port=$WORDPRESS_PORT"

Verification

Once completed or as you create this, you can verify your solution by manually checking with the following command line tools: docker, jq, and grep; or you can use automated verification using InSpec.

Manual Verification of Basic Features

Manual Verification of Adv Features

Automated Verification with InSpec

Once you download this script, you can run the tests with verify doing the following:

terraform apply
inspec
exec container_test.rb

When testing out an alternative port, you can do this:

export WORDPRESS_PORT=8888
terraform apply -var="wordpress_port=$WORDPRESS_PORT"
echo "port: $WORDPRESS_PORT" > attributes.yml
inspec exec container_test.rb --attrs=attributes.yml

Resources

To Be Continued

This article only details out the problem challenge and verification scripts, and afterward, I will present the final solution.

--

--

Joaquín Menchaca (智裕)

DevOps/SRE/PlatformEng — k8s, o11y, vault, terraform, ansible