Software Developer, Technology Enthusiast, Retro and Husband and Dad based in Melbourne.

Docker Compose and WordPress

Summary

This chapter walks through building and deploying a WordPress stack with Docker. It begins with a local development environment using Docker Desktop, then moves the same stack to AWS Lightsail using Docker’s remote SSH connection support.

The stack includes three main components:

  • WordPress for the website application.
  • MySQL for the database.
  • WP-CLI for managing WordPress from the command line.

These services are managed together using Docker Compose.

WordPress Docker Compose Stack

Clone the Sample Project

Before starting the WordPress stack, clone the sample project from GitHub:

git clone https://github.com/acj1971/wordpressawslightsailsamples

Then move into the sample folder for this chapter:

cd wordpressawslightsailsamples/Docker_Compose_and_Wordpress

This folder contains the docker-compose.yml file used throughout this chapter:


services:
  mysql:
    image: mysql:latest
    container_name: mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: wordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
    ports:
      - "3306:3306"
    volumes:
      -  mysql_data:/var/lib/mysql
    networks:
      - wp-network

  wordpress:
    image: wordpress:latest
    container_name: wordpress
    restart: always
    environment:
      WORDPRESS_DB_HOST: mysql:3306
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
    ports:
      - "80:80"
    volumes:
      - wp_html:/var/www/html
    depends_on:
      - mysql
    networks:
      - wp-network

  wpcli:
    image: wordpress:cli
    container_name: wpcli
    depends_on:
      - wordpress
    entrypoint: wp
    working_dir: /var/www/html
    volumes:
      - wp_html:/var/www/html
    environment:
      WORDPRESS_DB_HOST: mysql:3306
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
    networks:
      - wp-network

volumes:
  wp_html:
    external: true
  mysql_data:
    external: true

networks:
  wp-network:

Understanding a Docker Compose File for WordPress

Services

services:

The Docker Compose file defines a basic WordPress environment made up of three services. Each service runs in its own container and communicates with the other services through the same Docker network.

MySQL Service

mysql:

The mysql service runs the MySQL database container. It sets the root password, creates the WordPress database, and creates a WordPress database user. The database files are stored in the external mysql_data volume so they can be retained even if the container is recreated.

Image
image: mysql:latest

Using mysql:latest tells Docker to pull the most recent MySQL image rather than a fixed version. This can help keep the setup current, but the underlying version may change over time.

For a more predictable production setup, it is usually safer to pin the image to a specific version, such as 8.4. Upgrading between major versions or LTS releases can introduce compatibility or upgrade issues, so version changes should be planned carefully.

Container Name
container_name: mysql

This assigns the container the fixed name mysql, making it easier to identify and manage when using Docker commands, logs, and other administration tasks.

Restart
restart: always

This tells Docker to automatically restart the container if it stops or if the server is restarted. For a database service such as MySQL, this helps keep the WordPress stack available after a restart.

Environment
environment:
      MYSQL_ROOT_PASSWORD: wordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress

This section configures the initial MySQL setup. It sets the root password, creates the WordPress database, and creates a WordPress database user with a password. These values are then used by the WordPress container when connecting to MySQL.

In this example, the values are written directly in the Compose file for clarity. In a later chapter, these values will be managed using Docker Secrets for improved security.

Options Explained
  • MYSQL_ROOT_PASSWORD sets the password for the MySQL root user. In a later step, this value should be managed using Docker Secrets for improved security.
  • MYSQL_DATABASE defines the database that MySQL creates when the container starts for the first time.
  • MYSQL_USER creates a database user account when the container starts.
  • MYSQL_PASSWORD sets the password for the database user account. In a later step, this value should be managed using Docker Secrets for improved security.
Ports
ports:
      - "3306:3306"

This maps port 3306 on the host to port 3306 inside the MySQL container. Port 3306 is the standard MySQL port, and this mapping allows external access to the database if required.

WordPress does not require this host port mapping when both containers are connected to the same Docker network. In that case, WordPress connects internally using mysql:3306.

Volumes
volumes:
      - mysql_data:/var/lib/mysql

This volume mapping connects the Docker volume mysql_data to /var/lib/mysql inside the container. This directory is where MySQL stores its database files.

Networks
networks:
      - wp-network

Docker Compose networks allow containers to communicate without relying on fixed IP addresses. When services are connected to the same network, they can find and connect to each other by service name.

In this setup, wp-network provides communication between WordPress, MySQL, and WP-CLI.

WordPress Service

wordpress:

The wordpress service runs the main WordPress website using the selected WordPress image. It connects to the MySQL database using the settings provided in the environment variables. Port 80 is mapped so the site can be opened in a web browser, and the WordPress files are stored in the external wp_html volume.

The WordPress service also depends on the MySQL service, so Docker Compose starts the database container before starting WordPress.

Image
image: wordpress:latest

Using wordpress:latest tells Docker to use the most recent WordPress image available. This can include the latest bug fixes, security updates, and feature improvements.

For production environments, consider using a specific image tag so that updates can be tested before being applied.

Container Name
container_name: wordpress

This assigns the container the fixed name wordpress, making it easier to identify and manage when using Docker commands.

Restart
restart: always

This tells Docker to automatically restart the WordPress container if it stops or if the server is restarted. For a web service such as WordPress, this helps keep the site available when the stack restarts.

Environment
environment:
      WORDPRESS_DB_HOST: mysql:3306
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress

This section configures how the WordPress container connects to the MySQL database. It defines the database host, database name, username, and password used by WordPress.

These values must match the MySQL service settings so WordPress can communicate with the database correctly. In this example, the values are written directly in the Compose file for clarity, although Docker Secrets should be used for improved security.

Options Explained
  • WORDPRESS_DB_HOST tells WordPress how to connect to the database service. In this setup, mysql:3306 points to the MySQL service on the Docker network.
  • WORDPRESS_DB_NAME defines the name of the database WordPress will use.
  • WORDPRESS_DB_USER defines the username WordPress uses when connecting to the database service.
  • WORDPRESS_DB_PASSWORD defines the password WordPress uses when authenticating with the database service.

For improved security, sensitive credentials such as the database password should be managed using Docker Secrets.

Ports
ports:
      - "80:80"

This maps port 80 on the host to port 80 inside the WordPress container, allowing the site to be accessed in a web browser. Port 443 can be added in a later chapter to support HTTPS.

Volumes
volumes:
      - wp_html:/var/www/html

This volume mapping connects the Docker volume wp_html to /var/www/html inside the container. This is where WordPress stores its site files, including the wp-content folder.

Depends On
depends_on:
      - mysql

The depends_on setting tells Docker Compose to start the mysql service before the wordpress service. This helps ensure that the database container starts first, so WordPress can connect to it during startup.

Networks
networks:
      - wp-network

For the WordPress service, the Docker network allows it to communicate with MySQL and WP-CLI using service names instead of fixed IP addresses. In this setup, wp-network provides that internal connection.

WP-CLI Service

wpcli:

The wpcli service runs the WordPress CLI image, which allows you to manage the WordPress site from the command line. It uses wp as its entry point, works from /var/www/html, and shares the same wp_html volume as the WordPress service so it can access the same site files.

It also uses the same database connection settings as the WordPress service, ensuring WP-CLI commands operate against the same WordPress installation.

Image
image: wordpress:cli

Using wordpress:cli tells Docker to use the WordPress CLI image. This image provides the wp command-line tool for managing a WordPress site.

Container Name
container_name: wpcli

This assigns the container the fixed name wpcli, making it easier to identify and manage when using Docker commands.

Depends On
depends_on:
      - wordpress

This setting tells Docker Compose to start the wordpress service before the wpcli container.

Entrypoint
entrypoint: wp

This configures the container to use wp as its default command. As a result, WP-CLI commands can be run without specifying wp each time.

For example:

docker compose run --rm wpcli plugin list
Working Directory
working_dir: /var/www/html

This specifies /var/www/html as the working directory inside the container. It helps ensure that commands run from the WordPress root directory.

Volumes
volumes:
      - wp_html:/var/www/html

This volume mapping connects the Docker volume wp_html to /var/www/html inside the container. By sharing the same volume as the WordPress service, WP-CLI can work with the same WordPress files.

Environment
environment:
      WORDPRESS_DB_HOST: mysql:3306
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress

The environment variables in the wpcli service mirror those used by the wordpress service because both containers connect to the same WordPress database. This ensures that WP-CLI commands operate on the same site data and configuration as the main WordPress application.

Networks
networks:
      - wp-network

For the wpcli service, the Docker network allows it to communicate with WordPress and MySQL using service names instead of fixed IP addresses. In this setup, wp-network provides that internal connection.

Volumes

volumes:
  wp_html:
    external: true
  mysql_data:
    external: true

This section defines two named Docker volumes: wp_html and mysql_data.

  • wp_html stores the WordPress website files.
  • mysql_data stores the MySQL database files.
  • external: true tells Docker Compose to use an existing Docker volume rather than creating a new one.

This approach helps ensure that important data is stored independently of the containers, allowing it to persist even if the containers are recreated or updated.

Networks

networks:
  wp-network:

The networks section defines a custom Docker network named wp-network.

Docker Compose networks provide a straightforward way for containers to communicate without relying on fixed IP addresses. By connecting services to the same network, Docker allows them to discover and connect to one another using their service names.

In this stack, wp-network enables communication between WordPress, MySQL, and WP-CLI.

Start the WordPress Stack Using Docker Desktop

From inside the project folder wordpressawslightsailsamples/Docker_Compose_and_Wordpress, run:

docker compose up -d

Options Explained

  • docker compose manages multi-container applications using a Compose file.
  • up creates and starts the services defined in docker-compose.yml.
  • -d runs the containers in the background in detached mode.

What Starts Automatically

Docker Compose will create and start the following services:

  • mysql initializes the database and stores data in the mysql_data volume.
  • wordpress runs the web server and serves the site on port 80.
  • wpcli provides the command-line tool for managing the WordPress site.

On the first run, Docker downloads the required images:

  • mysql
  • wordpress
  • wordpress:cli

Docker then creates the containers, connects them to the wp-network, and attaches the external volumes wp_html and mysql_data to the appropriate services.

Verify the Stack Is Running

Option 1: Command Line

Run the following command:

docker compose ps

You should see the WordPress, MySQL, and WP-CLI services listed.

Option 2: Docker Desktop UI

Open Docker Desktop and locate the project container group, for example:

  • wordpress-docker

You should see the following services listed:

  • mysql
  • wordpress
  • wpcli

You can click each container to:

  • View logs.
  • Inspect environment variables.
  • Restart or stop the container.

Option 3: Start the Stack and Configure WordPress with WP-CLI

Start the WordPress stack in the background:

docker compose up -d

Once the containers are running, you can use WP-CLI to complete the initial WordPress setup from the command line. This will be covered in more detail in the Docker and WP-CLI chapter.

docker compose run --rm wpcli core install --url="http://localhost" \
  --title="My WordPress Site" \
  --admin_user="admin" \
  --admin_password="password" \
  --admin_email="admin@example.com"

Options Explained

  • docker compose manages multi-container applications using a Compose file.
  • run --rm starts a temporary container and removes it when the command finishes.
  • wpcli is the Docker Compose service that runs WP-CLI.
  • core install runs the wp core install command.
  • --url="http://localhost" sets the URL for the new site.
  • --title="My WordPress Site" sets the name of the new site.
  • --admin_user="admin" sets the username for the site administrator.
  • --admin_password="password" sets the password for the administrator account. If this option is not supplied, WordPress can generate a secure password automatically.
  • --admin_email="admin@example.com" sets the email address for the administrator account.

Access WordPress

Once the containers are running, open a web browser and go to:

http://localhost

This opens the local WordPress site. On the first visit, WordPress should display the initial setup screen unless the site has already been configured with WP-CLI.

View Logs for Troubleshooting

To view container logs, run:

docker compose logs -f

Options Explained

  • docker compose manages multi-container applications using a Compose file.
  • logs displays log output from the containers.
  • -f follows the logs in real time.

Stop the Stack

When you have finished working with the WordPress stack, you can stop the running containers using:

docker compose down

Because this project uses external Docker volumes, the following volumes are retained:

  • wp_html for the WordPress website files.
  • mysql_data for the MySQL database files.

Use Docker Compose with AWS Lightsail

The same Docker Compose stack can also be managed remotely on an AWS Lightsail instance. In this example, Docker connects to the Lightsail server over SSH using the Docker -H option.

Verify Remote Docker Access

First, confirm that Docker is available on your Lightsail instance:

docker -H ssh://MyUbuntuInstance info

Options Explained

  • docker runs the Docker command-line interface.
  • -H ssh://MyUbuntuInstance tells Docker to connect to the remote Docker host named MyUbuntuInstance over SSH.
  • info requests detailed information about the Docker environment on the remote host.

Start the WordPress Stack with Docker Compose

Once remote Docker access has been verified, start the WordPress, MySQL, and WP-CLI services on MyUbuntuInstance:

docker -H ssh://MyUbuntuInstance compose up -d

Options Explained

  • docker runs the Docker command-line interface.
  • -H ssh://MyUbuntuInstance connects Docker to the remote Lightsail instance over SSH.
  • compose runs Docker Compose commands against the selected Docker host.
  • up creates and starts the services defined in docker-compose.yml.
  • -d runs the containers in the background in detached mode.

Retrieve the Lightsail Static IP Address

Using the AWS CLI, you can retrieve the current static IP address assigned to the Lightsail instance MyUbuntuInstance:

aws lightsail get-static-ip --static-ip-name MyUbuntuInstanceStaticIP --region ap-southeast-2 --profile MyUbuntuProfile

Access WordPress Remotely

Once the containers are running, open a web browser and go to:

http://ipAddress

Replace ipAddress with the static IP address returned by the AWS CLI command.

Stop the WordPress Stack with Docker Compose

To gracefully stop the WordPress stack running on the remote Lightsail instance and remove the containers associated with the application, run:

docker -H ssh://MyUbuntuInstance compose down

Because this project uses external Docker volumes, the following volumes are retained:

  • wp_html for the WordPress website files.
  • mysql_data for the MySQL database files.

This means the site files and database are preserved even after the containers are removed.

Further Reading

Using WordPress on AWS Lightsail and Docker

Leave a Reply