Image for post
Image for post

Docker the Hard Way: Part 2

Solution for Orchestrating containers w Shell Scripting

In a previous article, I specified the problem to orchestrate creation of two containers, WordPress and MySQL 7.2, using the command. Some minimal features were to use persistent store for the database called , and allow for alternative port than the default .

This is the solution to that problem challenge.

Previous Article

The Solution in Shell

This is the full solution in POSIX shell programming using Bash:

Bash Solution

Solution Breakdown

In case some are new to either shell programming or Docker, here are some details about the code.

Default Variables

The first step is to specify some variables I use through the script, and default to , if it is not set in the environment:

WORDPRESS_PORT=${WORDPRESS_PORT:-'8080'}
MYSQL_VOLUME="db_data"
NETWORK_NAME="wordpress_net"

Create Persistent Volume Resource

We need to create a volume that will persist after reboots for the MySQL server:

docker volume create -d local --name $MYSQL_VOLUME

Create Network Resource

Now we create a network for these containers to use to communicate with each other. As this particular docker command is not idempotent, we have script around it to avoid errors:

docker network list | grep -q $NETWORK_NAME || \
docker network create $NETWORK_NAME

Deploy MySQL Container

Now we can create containers, first with MySQL and then WordPress. First we need to check to see if the containers are running already, and if they are, stop and remove them:

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

Now it is safe to run the container, run it:

docker run -d \
-v $MYSQL_VOLUME:/var/lib/mysql:rw \
--network=$NETWORK_NAME \
--restart=always \
-e MYSQL_ROOT_PASSWORD="wordpress" \
-e MYSQL_PASSWORD="wordpress" \
-e MYSQL_USER="wordpress" \
-e MYSQL_DATABASE="wordpress" \
--name "db" \
"mysql:5.7"

We will tell docker to use our volume and mount it at . We also want to run the container on the same network using .

The MySQL 5.7 image has built-in automation to create a user, user password, and database owned by that user, along with the root password, all by using environment variables sent to the container and launch (deploy) time.

Deploy WordPress Container

We stop and remove the WordPress container, should it be running:

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

Now, we can safely start the WordPress container on the same network as and map it’s internal port to a port we specify (or the default of ):

docker run -d \
--network=$NETWORK_NAME \
-p "$WORDPRESS_PORT:80" \
--restart=always \
-e WORDPRESS_DB_HOST="db:3306" \
-e WORDPRESS_DB_PASSWORD="wordpress" \
--name "wordpress" \
"wordpress:latest"

WordPress has some built-in automation using environment variables. Using the env , we can specify the database host address and database TCP port, in case it is different from .

The environment variables and will default to if not specified. The will need to be specified explicitly.

These environment variables will then be used to configure the WordPress app, i.e. file.

Wrapping Up

There you have it, a small shell script to use the Docker command to orchestrate a WordPress solution, which includes a persistent MySQL database.

Some takeaways for Docker:

  • Creating a volume resource and a network resource for containers to use.
  • Launching containers using deploy time configuration with environment variables.
  • Mapping remote port (from private container network) to host port

For shell scripting, in case you are unfamiliar with these:

  • Parameter expansion with to default variables if they are not already set
  • Using AND-OR Lists with or to control flow of commands
  • The POSIX xargs command to take output of one command and use it as the argument list of another command.

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