Wordpress
Wordpress is a free Content Management System, deployed in two docker containers here: one with the underlying database, the other with the Wordpress application itself.
Installation
The relevant installation steps comprise setting
environment variables in a .env
file. Thus, you need to create a hidden
file with the name .env
(including the '.') containing the following
environment variables:
WORDPRESS_DB_ROOT_PASSWORD=your_db_root_password
WORDPRESS_DB_NAME=your_db_name
WORDPRESS_DB_USER=your_db_user
WORDPRESS_DB_PASSWORD=your_db_password
TOP_LEVEL_DOMAIN=your_domain
SUB_DOMAIN=your_subdomain (in case of e.g. DynDNS redirection)
Additionally, the docker-compose
file configures a volume for the
content, Wordpress is displaying. This content is kept even when throwing
away the Docker image. The path on the host system is
/srv/www/wp-content
Navigating to this directory will show all files, Wordpress uses to display content, thus an existing backup can be restored here (database content needs to be taken care of separately, obviously).
Configuration
The docker-compose
file defines two services: the database and the
Wordpress application and connects them via the corresponding network
configuration.
Database
First, let's start with the database definition: it is a pretty simple and straightforward MySQL definition that
- defines the docker image to be downloaded from docker hub
- provides a name for our service (for easier recognition of the container and navigation e.g. in Portainer)
- reads all required variables from the
.env
file mentioned above - connects the database to the backend network (no need for the database to be addressed from outside)
wordpress-db:
image: hypriot/rpi-mysql
container_name: wordpress-db
restart: always
volumes:
- /srv/mysql:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=${WORDPRESS_DB_ROOT_PASSWORD}
- MYSQL_DATABASE=${WORDPRESS_DB_NAME}
- MYSQL_USER=${WORDPRESS_DB_USER}
- MYSQL_PASSWORD=${WORDPRESS_DB_PASSWORD}
networks:
- backend
The only thing worth mentioning is the volume for the content of the database. This is kept even when throwing away the Docker image and is mapped to
srv/mysql
Application
For the Wordpress application we need to do a little more. However, the first part is still pretty straightforward:
- defines the docker image to be downloaded from docker hub
- provides a name for our service (for easier recognition of the container and navigation e.g. in Portainer)
- creates a volume to map the Wordpress content into the container keeping its content also when throwing away the Docker image
- reads all required variables from the
.env
file mentioned above
image: wordpress:latest
container_name: wordpress-app
restart: always
volumes:
- /srv/www/wp-content:/var/www/html/wp-content
environment:
- WORDPRESS_DB_HOST=wordpress-db:3306
- WORDPRESS_DB_USER=${WORDPRESS_DB_USER}
- WORDPRESS_DB_PASSWORD=${WORDPRESS_DB_PASSWORD}
- WORDPRESS_DB_NAME=${WORDPRESS_DB_NAME}
A little more interesting is the Traefik configuration done via labels.
First, we enable Traefik to act as a proxy for this respective service
by setting the label traefik.enable
to true
.
Then we define the web-secure entrypoint for encrypted traffic (there is no need to do that for the unencrypted web entrypoint on port 80, since our Traefik configuration catches and redirects all unencrypted traffic to web-secure on port 443).
Most important is the router configuration which domains Traefik shall
route to the container for Wordpress to serve the content: here all
requests directed to the top level domain as configured in the environment
variable TLD
(e.g. example.org
) or sub-domain as configured in the
environment variable SD
(e.g. blog.example.org
). This can also be
useful if you use DynDNS providers mapping your top level domain to a
domain provided by the DynDNS provider.
The encryption via Let's Encrypt is enabled via the corresponding labels with the default resolver. This is being handled via Traefik as defined in the configuration of the Traefik container (via ACME).
labels:
- "traefik.enable=true"
- "traefik.http.routers.wp.entrypoints=web-secure"
- "traefik.http.routers.wp.rule=Host(`${TLD}`) || Host(`${SD}`)"
- "traefik.http.routers.wp.tls=true"
- "traefik.http.routers.wp.tls.certresolver=default"
- "traefik.http.services.wp.loadbalancer.server.port=80"
networks:
- backend
- traefik_proxy
Last, but not least, Wordpress is connected both to the traefik_proxy network so that is reachable from the internet and the backend network to ensure database connectivity.
Network
Last, but not least, we refer to the existing external networks... they need to exist as outlined here.
networks:
traefik_proxy:
external:
name: traefik_proxy
backend:
external:
name: backend