So far in our journey to deploy WordPress on Docker securely, we have installed Docker and Traefik. Now we get to the meat of the project. In this section, we will deploy 3 container services in the WordPress stack, ensuring our content management system is up and running within our Docker environment. We will configure the necessary services, including the WordPress application, its MariaDB database, and phpMyAdmin, and integrate them with Traefik for seamless traffic management and SSL termination. By the end of this part, you’ll have a fully functional and secure WordPress installation ready to serve your content to the world.
In this section, we’ll deploy WordPress, MariaDB (a popular MySQL-compatible database), and phpMyAdmin (a web-based database management tool) using Docker Compose. Docker Compose allows us to define and run multi-container Docker applications. Follow these steps to get your WordPress stack up and running.
Step 1: Set Up the Directory Structure
First, create a directory for your project and navigate into it:
mkdir wordpress-stack
cd wordpress-stack
mkdir php
cd php
WordPress is based on the PHP scripting language and in order for your site to work properly you will need to set some custom parameters in PHP. Let’s create a file called php_custom.ini
within the php
directory.
nano php.ini
In this file put the following:
file_uploads = On
memory_limit = 750M
upload_max_filesize = 750M
post_max_size = 750M
max_execution_time = 3200
max_input_vars = 5000
These will override the current php settings.
Step 3: Create the docker-compose.yml
File
Backing out of the php
directory into the wordpress-stack
directory, create a file named docker-compose.yml
:
nano docker-compose.yml
Copy the following into the docker-compose.yml
file:
services:
wordpress:
container_name: wordpress
image: wordpress:latest
restart: unless-stopped
depends_on:
- db
networks:
- proxy
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: wp_db
WORDPRESS_DB_USER: wp_user
WORDPRESS_DB_PASSWORD: WordPressDBPassword # change this!
TZ: America/New_York
volumes:
- ./php/php_custom.ini:/usr/local/etc/php/conf.d/wp-php.ini
- ./wordpress:/var/www/html
labels:
- "traefik.enable=true"
- "traefik.http.routers.wordpress.entrypoints=http"
- "traefik.http.routers.wordpress.rule=Host(`site.example.com`)"
- "traefik.http.middlewares.wordpress-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.wordpress.middlewares=wordpress-https-redirect"
- "traefik.http.routers.wordpress-secure.entrypoints=https"
- "traefik.http.routers.wordpress-secure.rule=Host(`site.example.com`)"
- "traefik.http.routers.wordpress-secure.tls=true"
- "traefik.http.routers.wordpress-secure.service=wordpress"
- "traefik.http.services.wordpress.loadbalancer.server.port=80"
- "traefik.docker.network=proxy"
# -----------------------------------------------------------------------
db:
container_name: db
image: mariadb:latest
restart: always
expose:
- 3306
ports:
- 3306:3306
networks:
- proxy
environment:
MYSQL_DATABASE: wp_db
MYSQL_USER: wp_user
MYSQL_PASSWORD: WordPressDBPassword # Change this!
MYSQL_ROOT_PASSWORD: RootPassword # Change this!
TZ: America/New_York
volumes:
- ./db:/var/lib/mysql
# -----------------------------------------------------------------------
phpmyadmin:
container_name: pja_phpmyadmin
image: phpmyadmin:latest
restart: always
depends_on:
- db
networks:
- proxy
environment:
- PMA_ARBITRARY=0
- PMA_HOST=db
- PMA_PORT=3306
labels:
- "traefik.enable=true"
- "traefik.http.routers.phpmyadmin.entrypoints=http"
- "traefik.http.routers.phpmyadmin.rule=Host(`phpmyadmin.sample.com`)" # Define rule for routing
- "traefik.http.middlewares.phpmyadmin-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.phpmyadmin.middlewares=phpmyadmin-https-redirect"
- "traefik.http.routers.phpmyadmin-secure.entrypoints=https"
- "traefik.http.routers.phpmyadmin-secure.rule=Host(`phpmyadmin.sample.com`)"
- "traefik.http.routers.phpmyadmin-secure.tls=true"
- "traefik.http.routers.phpmyadmin-secure.service=phpmyadmin"
- "traefik.http.services.phpmyadmin.loadbalancer.server.port=80"
- "traefik.docker.network=proxy"
networks:
proxy:
external: true
volumes:
wordpress:
db:
The labels
section in the docker-compose.yml
file is used to configure Traefik to manage routing, security, and other features for the WordPress service. Here’s a detailed breakdown of each label and its purpose:
traefik.enable=true
:- This label tells Traefik to enable routing for this particular container. Without this label, Traefik would ignore the container.
traefik.http.routers.wordpress.entrypoints=http
:- This defines an HTTP entry point for the
wordpress
router. An entry point is essentially a port that Traefik listens to for incoming requests.
- This defines an HTTP entry point for the
traefik.http.routers.wordpress.rule=Host(
site.example.com)
:- This sets a routing rule that directs traffic to the
wordpress
container when the host in the request matchessite.example.com
. This means Traefik will route requests intended forsite.example.com
to the WordPress service.
- This sets a routing rule that directs traffic to the
traefik.http.middlewares.wordpress-https-redirect.redirectscheme.scheme=https
:- This creates a middleware named
wordpress-https-redirect
that redirects HTTP traffic to HTTPS. Middlewares in Traefik are used to modify requests and responses.
- This creates a middleware named
traefik.http.routers.wordpress.middlewares=wordpress-https-redirect
:- This attaches the
wordpress-https-redirect
middleware to thewordpress
router, ensuring that all HTTP traffic gets redirected to HTTPS.
- This attaches the
traefik.http.routers.wordpress-secure.entrypoints=https
:- This defines an HTTPS entry point for the
wordpress-secure
router, meaning Traefik will handle HTTPS requests on the specified port.
- This defines an HTTPS entry point for the
traefik.http.routers.wordpress-secure.rule=Host(
site.example.com)
:- Similar to the HTTP router, this sets a routing rule for the
wordpress-secure
router to match the hostsite.example.com
.
- Similar to the HTTP router, this sets a routing rule for the
traefik.http.routers.wordpress-secure.tls=true
:- This enables TLS (Transport Layer Security) for the
wordpress-secure
router, ensuring that traffic is encrypted using HTTPS.
- This enables TLS (Transport Layer Security) for the
traefik.http.routers.wordpress-secure.service=wordpress
:- This defines the service that the
wordpress-secure
router should forward requests to, which is the WordPress container in this case.
- This defines the service that the
traefik.http.services.wordpress.loadbalancer.server.port=80
:- This specifies that the WordPress service is listening on port 80 inside the container. Traefik will forward requests to this port.
traefik.docker.network=proxy
:- This tells Traefik to use the
proxy
Docker network. The network must be created and used by both Traefik and the WordPress service for proper communication.
- This tells Traefik to use the
Step 4: Start the Docker Containers
With the docker-compose.yml
file in place, you can start the services using the following command:
docker compose up -d
The -d
flag runs the containers in detached mode, allowing them to run in the background.
Step 5: Verify the Deployment
- Access WordPress: Open a web browser and navigate to
https://sample.com
. You should see the WordPress installation screen. Follow the on-screen instructions to complete the setup.
- Access phpMyAdmin: Open another tab in your web browser and navigate to
https://phpmyadmin.sample.com
. You should see the phpMyAdmin login screen.
Conclusion
By following these steps, you’ve successfully deployed WordPress, MariaDB, and phpMyAdmin using Docker Compose. This setup provides a robust and scalable environment for managing your WordPress site and its database, with the added convenience of phpMyAdmin for database management. You can further enhance this setup by integrating Traefik for dynamic routing and SSL termination. In the next post, we will add the final component, CrowdSec to our deployment of WordPress on Docker.