Image for post
Image for post

Docker the Easy Way — Part 2

Solution for Orchestrating containers with Docker Compose

This is the solution for orchestrating docker containers using Docker Compose tool in four stages.

Previous Article

The Starter Script

In the previous article, we started with a very basic docker-compose.yml script. Now we will fill this out.

Solution in Stages

I have separated the solution into stages to demonstrate and discuss the features of Docker Compose, from the simplest solution to a more complex solution, adding a layer of complexity as we go.

In the first stage, we just bring up the two containers and set them to have a restart policy of always, and give them respective container names of db and wordpress.

We pass in environment variables to trigger the container’s internal automation that allow them to self-configure (see the document for mysql and wordpress on Docker Hub for further information).

The Wordpress container will map the container port of 80 to the host port of 8080.

For the second stage, we will add in support for a persistent volume, and mount it to /var/lib/msyql.

The actual name of the volume resource is not db_data, but for the purposes of this script, db_data is the label to connect a volume created by Docker Compose to a volume used by the container.

Now we add support for the external environment variable WORDPRESS_PORT, which is now used to set the host port that is mapped to the container’s port 80.

NOTE: Be care not to confuse environment variables passed to and used by Docker Compose, and environment variables declared in Docker Compose DSL that are passed to the containers themselves.

Now that we support the environment variable, the script will FAIL. Why?

If the environment variable WORDPRESS_PORT is not set when we run, Docker Compose will pass a blank value to the mapping, which causes it to fail. So we need to set a default value somewhere.

We can set defaults in an environment file (.env) file in the same directory:

echo WORDPRESS_PORT=8080 > .env

Now the script runs regardless of WORDPRESS_PORT setting:

docker-compose up -d  # success with 80:8080 mapping
docker-compose stop && docker-compose rm
export WORDPRESS_PORT=8888
docker-compose up -d # success with 80:8888 mapping

At this point, we want to take wrest control for both the network and volume resources, instead of letting Docker Compose automatically create a private network on our behalf.

We can do this by updating docker-compose.yml to match the following below, so that we use a private network with the explicit label of wordpress_net, and also force the volume name to be explicitly db_data:

After this stage, running the verification script with InSpec should produce the positive results.

Stages in Practice

For most cases, you can let Docker Compose handle the automation of naming containers, volumes, and networks. This works for small segregated development environments, which is useful for Continuous Integration testing pipelines.

The moment you need to integrate with automation outside of Docker Compose, you may need to explicitly name volumes or networks, then lessons in Stage 4 become important.

The systems tests we created in InSpec also require that Stage 4 is completed.


This completes the Docker Compose tutorial with problem-challenge and solution. We walked through the features in Docker Compose in four stages, with the final stage using version 3.7 of the Docker Compose DSL.

I have used Docker Compose successfully in the past to build tooling for both local dev-test environments on laptops and build-test systems that used a popular CI-CD solution.

For these environments, I let Docker Compose dynamically name the containers and private container networks, and I never used persistence, as I created the data schema (db-migrate) and populated (db-seed) tables with test data, so this required starting from scratch.

Written by

Linux NinjaPants Automation Engineering Mutant — exploring DevOps, Kubernetes, CNI, IAC

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