2 min read

Containerised Hosting [3/3]: Wordpress

Part 3 of A tutorial on setting up your own web hosting service with automation and security using Ubuntu, Docker, Traefik, Let's Encrypt and more!
Containerised Hosting [3/3]: Wordpress

Hello Everybody! Tansanrao here, Welcome to part 3 of the Containerised Hosting series, today we will be setting up Wordpress to run as a separate stack.

Step 1 - Create a docker compose file

version: "3.3"

services:
  mysql:
    image: mysql:8.0
    container_name: mysql
    restart: unless-stopped
    env_file: .env
    environment:
      - MYSQL_DATABASE=wordpress
    volumes:
      - mysql:/var/lib/mysql
    command: "--default-authentication-plugin=mysql_native_password"
    networks:
      - private

  wordpress:
    depends_on:
      - mysql
    container_name: wordpress
    restart: unless-stopped
    image: wordpress:5.5.0-php7.4-apache
    env_file: .env
    environment:
      - WORDPRESS_DB_HOST=mysql:3306
      - WORDPRESS_DB_USER=$MYSQL_USER
      - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD
      - WORDPRESS_DB_NAME=wordpress
    labels:
      - traefik.enable=true
      - traefik.http.middlewares.redirect-websecure.redirectscheme.scheme=https
      - traefik.http.routers.wordpress-web.rule=Host(`example.com`)
      - traefik.http.routers.wordpress-web.entrypoints=web
      - traefik.http.routers.wordpress-web.middlewares=redirect-websecure
      - traefik.http.routers.wordpress-websecure.entrypoints=websecure
      - traefik.http.routers.wordpress-websecure.rule=Host(`example.com`)
      - traefik.tags=traefik-public
      - traefik.docker.network=traefik-public
      - traefik.http.routers.wordpress-websecure.tls=true
      - traefik.http.routers.wordpress-websecure.tls.certresolver=myresolver
    volumes:
      - wordpress:/var/www/html/wp-content
      - ./upload.ini:/usr/local/etc/php/conf.d/uploads.ini
    networks:
      - private
      - traefik-public

volumes:
  wordpress:
  mysql:

networks:
  private:
    driver: bridge
  traefik-public:
    external: true

In the above docker-compose file, we are defining 4 major things, The Database, The Wordpress Install, Persistent Volumes for the 2, and networks for the stack.

We first create the mysql service using the image mysql:8.0. We set the container name, set a restart policy to auto-restart the container unless manually stopped, we tell it to load environment variables from a file called .env, and we assign the persistent volume mysql as shown mysql:/var/lib/mysql. We also pass the command flag "--default-authentication-plugin=mysql_native_password" to force mysql 8.0 to use the older password scheme to maintain compatibility with mysql 5 clients.

Similarly we define the wordpress service, we attach the volume wordpress to wordpress:/var/www/html/wp-content to provide persistence for uploaded content. We also pass in a custom upload.ini file to configure php like so ./upload.ini:/usr/local/etc/php/conf.d/uploads.ini (more on this later).

The Traefik labels attached are explained in Part 2 of this series here.

We then define the required volumes and networks at the end of the file.

Step 2 - Create a .env file

Create a file called .env in the same directory as the docker-compose file

nano .env

Enter the following and make sure you change the passwords

MYSQL_ROOT_PASSWORD=ghost
MYSQL_USER=ghost
MYSQL_PASSWORD=ghost

This file is used to pass on the environment variables without adding credentials in the GitHub repo.

Step 3 - Create upload.ini to override php

Create a file called upload.ini in the same directory as the docker-compose file

nano upload.ini

Enter the following:

file_uploads = On
memory_limit = 512M
upload_max_filesize = 512M
post_max_size = 512M
max_execution_time = 600

This allows Wordpress to accept file uploads up to 500mb in size, and allows php execution to continue for 600 seconds before being killed.

And that’s it!

docker-compose up -d

And you are good to go!

As always, You can refer the repository here for the entire structure and final state of each file.

Follow me on Twitter & Instagram for behind the scenes and updates.