Aslam Doctor

Docker WordPress Web Development Stack

Docker WordPress Web Development Stack

I have been using LAMP stack using WSL on Windows for a very long now and it is excellent. But it is not very flexible like Docker. While setting up Docker for WordPress-based projects, there are so many options but I came up with my own solution. First I listed out my primary requirements which are – The stack should contain WordPress, WordPress CLI, MySQL, PHPMyAdmin, Apache, and also a tool for supporting reverse proxy so that I can host multiple docker containers and point them to the right domains locally.

WordPress

Docker already has an official image for WordPress and It comes with Apache & WordPress CLI inbuilt. The specific image tag I used is wordpress:6.0.1-php7.4-apache

Below is the code for the WordPress service. I will explain about the traefik further down the article.

wordpress:
    depends_on:
      - db
    image: wordpress:6.0.1-php7.4-apache
    expose:
      - ${WP_PORT}
    volumes:
      - './wordpress:/var/www/html'
      - './config/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini'
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:${DB_PORT}
      WORDPRESS_DB_USER: ${MYSQL_DATABASE}
      WORDPRESS_DB_PASSWORD: ${MYSQL_USER}
      WORDPRESS_DB_NAME: ${MYSQL_PASSWORD}
    networks:
      - traefik
      - backend
    labels:
      # The labels are usefull for Traefik only
      - 'traefik.enable=true'
      - 'traefik.docker.network=traefik'
      # Get the routes from http
      - 'traefik.http.routers.$TRAEFIK_ROUTE.rule=Host(`${SITE_URL}`)'
      - 'traefik.http.routers.$TRAEFIK_ROUTE.entrypoints=web'

And below is for WP-CLI as it comes inbuilt with the official WordPress image.

  wp-cli:
    image: wordpress:cli-2.6.0-php7.4
    depends_on:
      - wordpress
      - db
    environment:
      WORDPRESS_DB_HOST: db:${DB_PORT}
      WORDPRESS_DB_USER: ${MYSQL_DATABASE}
      WORDPRESS_DB_PASSWORD: ${MYSQL_USER}
      WORDPRESS_DB_NAME: ${MYSQL_PASSWORD}
    working_dir: /var/www/html
    volumes:
      - './wordpress:/var/www/html'
    networks:
      - backend

Mysql & PHPMyAdmin

For MySQL also I used an official docker image. The specific image tag I used was mysql:5.7 as I wanted to use MySQL version 5.7. And for phpMyAdmin, I used this docker image.

Below is the code for the MySQL service.

db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    networks:
      - backend

And below is for the phpMyAdmin service.

depends_on:
      - db
    image: phpmyadmin/phpmyadmin
    container_name: ${PMA_CONTRAINER_NAME}
    links:
      - db
    environment:
      PMA_HOST: db
      PMA_PORT: ${DB_PORT}
      PMA_ARBITRARY: 1
    restart: always
    ports:
      - ${PMA_PORT}:80
    networks:
      - backend

You can get the Full Combined code from here.

https://github.com/aslamdoctor/docker-wordpress/blob/main/docker-compose.yml

Reverse Proxy using Traefik image

Traefik is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy. Let’s say you have used this docker container to create multiple WordPress websites, so you have to run the container multiple times and also each website will be hosted to different ports. On windows systems, you can not add ports to host file, which means you can not point each site to a specific domain without using port. It will look something like this.

http://website1.local (if it uses port 80)
http://website2.local:81
http://website3.local:82
http://website4.local:84

So to stop using these port numbers, we need a reverse proxy mechanism. There are multiple options for this. We can also do this using Ngnix proxy manager tool but I prefer using Traefik.

To use Traefik, we have to create a separate container that acts as a proxy manager for all the other WordPress containers. Below is the code for my Traefik docker container.

version: '3.3'

networks:
  # Allow the use of traefik in other docker-compose.yml files
  traefik:
    external: true
services:
  traefik:
    # The official v2 Traefik docker image
    image: traefik:v2.8
    container_name: 'traefik'
    logging:
      options:
        max-size: '10m'
        max-file: '3'
    command:
      # Only for development environment
      - '--log.level=DEBUG'
      - '--api.insecure=true'
      # Get Docker as the provider
      - '--providers.docker=true'
      # Avoid that all containers are exposed
      - '--providers.docker.exposedbydefault=false'
      # Settle the ports for the entry points
      - '--entrypoints.web.address=:80'
      - '--entrypoints.web-secure.address=:443'
    ports:
      - '80:80'
      - '443:443'
      - '8080:8080'
    networks:
      - 'traefik'
    volumes:
      # Connect to Doker socket
      - '/var/run/docker.sock:/var/run/docker.sock:ro'

And the last most important thing is environment configurations. You have to make the required changes in the .env file. Change the values where the comments says #Must be unique

WP_PORT=80 #Must be unique

#Phpmyadmin
PMA_PORT=6060 #Must be unique
PMA_CONTRAINER_NAME=phpmyadmin_pma #Must be unique

# DB Variables
MYSQL_ROOT_PASSWORD=somewordpress
MYSQL_DATABASE=wordpress
MYSQL_USER=wordpress
MYSQL_PASSWORD=wordpress
DB_PORT=3306

# Traefik Configurations
SITE_URL=mywebsite.local #Must be unique
TRAEFIK_ROUTE=mywebsite #Must be unique

For more information on how to run this container, head over to my GitHub repository and follow the readme.md file.

https://github.com/aslamdoctor/docker-wordpress

Thank You