Docker the Pythonic Way

Orchestrating containers with Docker SDK for Python

Joaquín Menchaca (智裕)
5 min readMay 25, 2019

--

Earlier I demonstrated on how use Python use some shell interactivity in order to automate container orchestration through the Docker CLI command docker.

I’m not going to lie, Python, is well, perhaps not a pretty sight with regards to using subshell with popen(). Best advice, unless absolutely need to interact with the shell, just don’t do it.

However with Python, you can just talk to the Docker service directly through the Docker SDK or Python, otherwise known as docker-py.

This Python library is what is used for both Ansible docker modules and Docker Compose tool. So let’s go directly to the source, and use the library instead of higher level tools.

Problem

The goal of this exercise bring up fully functional WordPress environment that you can use for your development delights. This means using Python to orchestrate two containers. Below are featured organized into basic and advanced.

When completed, name the script docker_sdk.py or other suitable name, and run it to verify it features manually or with Inspec script listed in Verification section.

Basic Feature Requirements

We want to bring up the containers and verify they work.

Basic Feature Requirements

For this we want to do the following:

  1. Launch MySQL (mysql:5.7) with restart policy of always, intuitive name of db, and to triggering internal container configuration by passing environment variables to setup root password, and a wordpress database, user, and password.
  2. Launch WordPress (wordpress:latest) with restart policy of always, intuitive name of wordpress, map the container port of 80 to host port of 8080, and to triggering internal container configuration by passing environment variables to setup

Advanced Feature Requirements

For this, we want to support put our containers on a private network, use a persistent volume for the MySQL database, and allow the user to specify the host port with WORDPRESS_PORT environment variable.

Advanced Feature Requirements

We will do this to implement the features:

  1. Create a volume resource and mount it as /var/lib/mysql for the db container.
  2. Create a network resource and configure both containers to use the private network.
  3. Set the host port to the environment variable WORDPRESS_PORT, and if this is not set, then default it to port 8080

Verification

You can manually verify the solution or use the automated InSpec script to verify the results.

Manually Verification of Basic Features

With docker inspec, jq, and grep, you features as depicted by the graphic below:

Manual Verification of Basic Features

Manual Verification of Advanced Features

With docker inspec, jq, and grep, you features as depicted by the graphic below:

Automated Verification

With InSpec (gem install inspec && gem install inspec-bin), you can verify both basic and advance features:

Download the script as container_test.rb, and run it:

inspec exec container_test.rb

If you set an alternative port with WORDPRESS_PORT, you can verify using the following commands:

echo "port: $WORDPRESS_PORT" > attributes.yml
inspec exec container_test.rb --attrs=attributes.yml

Underrepresented Testing

Back in the day, testers were challenged to break the application, but these days, it seems that testing is regulated to developers verifying features are completed. For this reason, I call these underrepresented testing instead of negative, destructive, or edge testing.

At minimum, in any change system, you want verify that the automation idempotent, where running it more than once produces the same results. It definitely should not give you a traceback, or create new resources with the same name, such as multiple networks with the wordpress_net name.

Here are some additional tests that you may want (or not want) to try with the final solution:

Clean Up Script

You can use this to erase your environment and start over again should you need it.

Removing Containers

docker ps -f name=wordpress -q | xargs docker stop && \
docker ps -f name=wordpress -aq | xargs docker rm
docker ps -f name=db -q | xargs docker stop && \
docker ps -f name=db -aq | xargs docker rm

Removing Volume and Network Resources

docker volume rm db_data
docker network ls -f name=wordpress_net -q | xargs docker network rm

Validation

For validation, you would point your web browser to the host port, and interact with the WordPress application.

For the database persistence, create stuff, maybe like a blog post. Then stop and remove the MySQL db container, and recreate it, making sure not to remove the volume db_data. The data should still exist after this process.

Resources

References

Formal Requirements Document

Related Articles

Problem for Docker CLI

Solution for Docker CLI in Shell Programming

Solution for Docker CLI in Python, Ruby, and Perl

Last Thoughts

For this article, I presented the problem and how to test and validate it. I hope you can try out Inspec script to test your solution to get a sample of TDD for systems programming.

In a follow-up article, I will present the solution.

--

--

Joaquín Menchaca (智裕)
Joaquín Menchaca (智裕)

Written by Joaquín Menchaca (智裕)

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

No responses yet