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.
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
The Wordpress container will map the container port of
80 to the host port of
For the second stage, we will add in support for a persistent volume, and mount it to
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
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
docker-compose up -d # success with 80:8080 mapping
docker-compose stop && docker-compose rmexport 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
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.