Wordpress

Deploy Wordpress #

We selected Wordpress as an example because this setup comes with the following:

  • a webserver (nginx) in front of the Wordpress application
  • PHP app server (php-fpm) for Wordpress
  • database for Wordpress to use

In addition, there is:

  • a shared volume between the webserver and wordpress (for assets)
  • multiple networks (e.g. one for Wordpress app server and DB only)
  • connection to the public network Quantum creates for you
  • instant SSL through Traefik and Let’s Encrypt

Let’s get started!

Nginx #

At first, we define an nginx and a configuration optimized for Wordpress.

We use a stock nginx as a base image and add our own configuration to it — removing/overwriting the default virtualhost.

Dockerfile:

FROM nginx:1.15.12-alpine

RUN rm -f /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf

This is a copy of the nginx.conf file which should be next to the Dockerfile:

server {
        listen 80;
        listen [::]:80;

        server_name localhost;

        error_log /dev/stdout info;
        access_log /dev/stdout;

        index index.php index.html index.htm;

        root /var/www/html;

        location / {
                try_files $uri $uri/ /index.php$is_args$args;
        }

        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass wordpress:9000;
                fastcgi_index index.php;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_param PATH_INFO $fastcgi_path_info;
        }

        location ~ /\.ht {
                deny all;
        }

        location = /favicon.ico {
                log_not_found off; access_log off;
        }
        location = /robots.txt {
                log_not_found off; access_log off; allow all;
        }
        location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
                expires max;
                log_not_found off;
        }
}

The next steps are to docker build and push the nginx image to your private registry:

$ docker build -t registry.example.org/wordpress/nginx:latest -f Dockerfile .
...
$ docker login -u username -p password registry.example.org
...
$ docker push registry.example.org/wordpress/nginx:latest
...

Please note: you need to adjust registry.example.org and credentials to what you need in your environment. Ideally these steps are part of your CI pipeline using Drone.io or Gitlab, or a managed service such as CircleCI.

If you don’t have a private registry yet, you can deploy one on Quantum.

Docker Swarm #

The next step is to assemble it all within a Docker Swarm stack file. Docker Swarm is an orchestrator for our different services.

In the following example we have a database (db), Wordpress (wordpress) and nginx (webserver). The first two use official image from Docker Hub, the webserver is the custom image we built in the previous step.

docker-compose.yml:

version: "3.8"

services:
  db:
    image: mariadb:10.4
    restart: unless-stopped
    environment:
      - MYSQL_ROOT_PASSWORD=test123
      - MYSQL_USER=wordpress-dbo
      - MYSQL_PASSWORD=123test
      - MYSQL_DATABASE=wordpress
    volumes:
      - dbdata:/var/lib/mysql
    command: '--default-authentication-plugin=mysql_native_password'
    networks:
      - wp-db-internal

  wordpress:
    depends_on:
      - db
    image: wordpress:5.2.2-fpm-alpine
    restart: unless-stopped
    environment:
      - WORDPRESS_DB_HOST=db:3306
      - WORDPRESS_DB_USER=wordpress-dbo
      - WORDPRESS_DB_PASSWORD=123test
      - WORDPRESS_DB_NAME=wordpress
    volumes:
      - wordpress:/var/www/html
    networks:
      - wp-db-internal
      - wp-internal

  webserver:
    depends_on:
      - wordpress
    image: registry.example.org/wordpress/nginx:latest
    restart: unless-stopped
    deploy:
      labels:
        traefik.enable: "true"
        traefik.docker.network: "public"
        traefik.port: "80"
        traefik.frontend.rule: "Host:wordpress.example.org"
    volumes:
      - wordpress:/var/www/html
    networks:
      - public
      - wp-internal

volumes:
  wordpress:
    driver: local
  dbdata:
    driver: local

networks:
  wp-internal:
  wp-db-internal:
  public:
    external:
      name: public

Please note: Ensure the Docker image used is the one you pushed to your private registry. It’s also a good idea to use better passwords, etc..

Done! #

Last but not least, you should use quantum-cli to deploy the stack or log into the Quantum Console and e.g. copy paste your Docker Compose/Swarm configuration into a new stack!