Deploy WordPress with Docker, Traefik, and CrowdSec for Enhanced Security – Part 3

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:

  1. traefik.enable=true:
    • This label tells Traefik to enable routing for this particular container. Without this label, Traefik would ignore the container.
  2. 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.
  3. 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 matches site.example.com. This means Traefik will route requests intended for site.example.com to the WordPress service.
  4. 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.
  5. traefik.http.routers.wordpress.middlewares=wordpress-https-redirect:
    • This attaches the wordpress-https-redirect middleware to the wordpress router, ensuring that all HTTP traffic gets redirected to HTTPS.
  6. 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.
  7. 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 host site.example.com.
  8. 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.
  9. 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.
  10. 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.
  11. 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.

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.

Leave a Comment

Your email address will not be published. Required fields are marked *