Building a website with docker is absolutely an enjoyable experience. With prebuilt images we are allowed to focus more on wiring and configuring different components instead of taking time to setup environment for each one of them. And with several configuration files, we are able to reproduce the same process from scratch as many times as we want.
To quantify the simplicity, this whole process of building an SSL encrypted, Google Analytics monitored website with stunning UI will take you less than 10 minutes. Sounds attractive? Then let’s get started!
Prerequisite
- Host with clean Ubuntu 18.04 LTS
- Domain with A record pointing to the host’s IP (in my case “bd16s.com”)
Objectives Breakdown
- Step 1: Install docker and docker-compose
- Step 2: Start WordPress container backed by MySQL container
- Step 3: Run linuxserver/letsencrypt image
- This image will fetch the SSL Certificate
- This image will also bring up an Nginx server, which can serve as a reverse proxy server
- Step 4: Configure Google Analytics
Step 1: Install docker and docker-compose
Install docker
There are many good tutorials for installing docker on Ubuntu, for example this one from DigitalOcean is very clear and detailed. Here I take some commands and explanations we need from the post.
# First, update your existing list of packages:
sudo apt update
# Next, install a few prerequisite packages which let apt use packages over HTTPS:
sudo apt install apt-transport-https ca-certificates curl software-properties-common
# Then add the GPG key for the official Docker repository to your system:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# Add the Docker repository to APT sources:
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
# Next, update the package database with the Docker packages from the newly added repo:
sudo apt update
# Finally, install Docker:
sudo apt install docker-ce
At this point, we should have docker-ce installed on host, and the docker daemon should be running.
Install docker-compose
The install procedure for docker-compose can be found from here in Docker Documentation. Replace version number 1.23.2 with the latest version listed on GitHub release page.
# Download the latest version of Docker Compose:
sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# Apply executable permissions to the binary:
sudo chmod +x /usr/local/bin/docker-compose
Now docker-compose is installed.
Step 2: Start WordPress and MySQL
Prepare docker-compose.yml file:
version: '3.3'
services:
wordpress:
depends_on:
- mysql
image: wordpress:5.0.2
volumes:
- ./wordpress_files/var/www/html:/var/www/html
expose:
- "80"
restart: always
container_name: wordpress
environment:
WORDPRESS_DB_HOST: mysql:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: <wordpress_password_placeholder>
db_mysql:
image: mysql:5.7
volumes:
- ./mysql_data/var/lib/mysql:/var/lib/mysql
expose:
- "3306"
restart: always
container_name: wordpress-mysql
environment:
MYSQL_ROOT_PASSWORD: <root_password_placeholder>
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: <wordpress_password_placeholder>
This file tells docker-compose to start to containers, one with PHP and WordPress and the other with MySQL. Each container has a shard mount with local storage, thus data will be persisted outside the containers and so containers themselves can be seen as stateless. With this configuration, the exposed ports are only accessible from within the docker bridge, but not outside. This is because we are going to use a reverse proxy server in front of it, and only that server should be exposed to public. Once configured as above, start containers by running:
sudo docker-compose up -d
Reference:
Step 3: Run linuxserver/letsencrypt
For free SSL/TLS Certificates, the most popular provider is “Let’s Encrypt”. It is popular enough that docker images are created and actively maintained. Here we use image from linuxserver/letsencrypt, which will handle the verification process, and renew the certificate every month. It also provides an Nginx server out of the box, which can be used as a reverse proxy server for wordpress.
Start Container
Since we only have one container to start, follow the instruction from official documentation and simply run it from terminal with the following command:
sudo docker run -d --network="wordpress_default"\
--cap-add=NET_ADMIN \
--name=letsencrypt \
-v <path to data>:/config \
-e PGID=<gid> -e PUID=<uid> \
-e EMAIL=<email> \
-e URL=bd16s.com \
-e SUBDOMAINS=www \
-e VALIDATION=http \
-p 80:80 -p 443:443 \
-e TZ=<timezone> \
linuxserver/letsencrypt:196
Here use id <username> to get PGID and PUID, and since we want this container to talk to other containers in the virtual network, we need to specify the network name.
It will take some time to validate the domain and get the certificate for the first time. Once the container is fully started, it will create the config folder.
Edit Nginx Proxy Configuration
From the config folder we need to tell Nginx to forward requests to wordpress container. go to config/nginx/site-confs and edit the default file. Here is the config file I’m using.
# redirect all traffic to https
server {
listen 80;
listen [::]:80;
server_name _;
return 301 https://$host$request_uri;
}
# main server block
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name _;
# enable subfolder method reverse proxy confs
include /config/nginx/proxy-confs/*.subfolder.conf;
# all ssl related config moved to ssl.conf
include /config/nginx/ssl.conf;
client_max_body_size 0;
location / {
proxy_pass http://wordpress:80;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Configure WordPress
Follow the instruction from Heiner’s Blog and:
- Install and activate plugin “SSL Insecure Content Fixer”
- Go to Settings >> SSL Insecure Content Fixer settings >> HTTPS detection, and select “HTTP_X_FORWARDED_PROTO (e.g. load balancer, reverse proxy, NginX)”
- Go to Settings >> General Settings, and set both “WordPress Address (URL)” and “Site Address (URL)” to the domain name
Step 4: Configure Google Analytics
Add plugin MonsterInsights to WordPress and set the tracking ID. This tracking ID can also be used by Google Search Console to verify the ownership of the website.
Extra Step: Sit Back and Enjoy!
Now with all jobs done, get a cup of tea and enjoy the awesome website, cheers!