WordPress from Development to Production using Docker Part II
This post continues where part one left off. Topics include mysql data migration, staging and production docker configurations with optional https.
To perform these steps, you will need to either:
- Create the files directly on the server using nano, vim or some other command line editor.
- Create the files on your local machine and copy them to the server using scp.
I prefer the latter method. Creating the files locally in a folder structure that mirrors my home directory on the server makes it easier to edit and deploy them to the respective server. Not to mention the local backup this creates. Use scp from the command line or use a GUI application such as FileZilla or WinSCP.
Reverse Proxy
For staging and production, create a docker-compose.yml
file that defines a reverse-proxy service using the official Traefik image. It is a good idea to put the Traefik Docker files in its own folder to make it easier when adding more sites later. Create a folder on the server for your Traefik files and save the compose yaml there.
docker-compose.yml
version: "3"
services:
proxy:
image: traefik:v1.7
restart: unless-stopped
# command: --docker --logLevel=DEBUG
command: --docker --logLevel=INFO
networks:
- webgateway
ports:
- "80:80"
- "8080:8080"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./certs:/etc/traefik/certs
# `chmod 600 acme.json`
- ./acme.json:/etc/traefik/acme.json
- ./traefik.toml:/etc/traefik/traefik.toml
# - $PWD/.htpasswd:/etc/traefik/.htpasswd
networks:
webgateway:
driver: bridge
update: note that we’re pulling a traefik version 1 image in the docker-compose.yml
above. The traefik:latest
image switched to version 2 a little over a year after this post was originally published. A configuration migration guide can be found here should you want to use version 2.
This Traefik
docker-compose.yml
uses Let’s Encrypt for free SSL certificate renewal. Create atraefik.toml
andacme.json
file to set that up. If you already have an SSL certificate for your site, use thecerts
folder to store the certificate files there for mounting to the Traefik container.
traefik.toml
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
# comment these lines if not in use
# non let's encrypt certificates
[[entryPoints.https.tls.certificates]]
certFile = "/etc/traefik/certs/myothersite.com.crt"
keyFile = "/etc/traefik/certs/myothersite.com.key"
[acme]
email = "gilfoyle@piedpiper.com"
storage = "acme.json"
onHostRule = true
# caServer = "http://172.18.0.1:4000/directory"
entryPoint = "https"
[acme.httpChallenge]
entryPoint = "http"
For staging, comment out the lines for https in
traefik.toml
as needed. More information on how to do this is included in my recent post: VPS Proof of Concept for Docker and Traefik.
The acme.json
file is used by Traefik for certificate storage. Create this file and set the permissions to 600 so only the owner can read and write. For example.
# change to the folder where our Traefik docker files are stored
cd docker/traefik
# create an empty acme.json file
touch acme.json
# set permissions to 600
chmod 600 acme.json
Site
Once your docker image is deployed, you are ready to create a staging and production docker-compose.yml
file for mysite.
docker-compose.yml
version: '2'
services:
app:
image: mysite:4.9.6-1.0
restart: unless-stopped
environment:
- WORDPRESS_DB_HOST:mysql:3306
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=changeme!
- WORDPRESS_DB_NAME=wordpress
labels:
- traefik.frontend.rule=Host:local.vm.mysite.com
- traefik.docker.network=traefik_webgateway
volumes:
- app:/var/www/html
networks:
- web
- backend
links:
- mysql
mysql:
image: mariadb
restart: unless-stopped
labels:
- "traefik.enable=false"
environment:
- MYSQL_ROOT_PASSWORD=changeme!
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=changeme!
volumes:
- mysql:/var/lib/mysql
networks:
- backend
networks:
web:
external:
name: traefik_webgateway
backend:
driver: bridge
volumes:
app:
mysql:
For production, replace label
traefik.frontend.rule=Host:local.vm.mysite.com
with the registered host. You can specify both without and withwww
, for example:traefik.frontend.rule=Host:mysite.com,www.mysite.com
.
To recap, here is how we have structured our Docker files in the users home folder on the server for mounting them to volumes and running the containers with docker-compose
. The docker/traefik/certs
folder is only needed for non Let’s Encrypt certificate storage, for example, certificates purchased from SSLs.com. Note that we did not create an additional site, e.g., myothersite
. It is included below only to demonstrate that multiple sites can be added using this setup and they can use either Let’s Encrypt or purchased certs.
- docker
- mysite
- docker-compose.yml
- myothersite
- docker-compose.yml
- traefik
- docker-compose.yml
- acme.json
- traefik.toml
- certs
- mysite
Run
Start the containers on the server using docker-compose
. Do this by opening a secure shell using ssh
. For example,
ssh gilfoyle@172.10.10.10
# change to the directory where you uploaded the
# traefik docker-compose.yml file using scp
cd docker/traefik
# start the traefik container
docker-compose up -d
# change to the directory where you uploaded the
# mysite docker-compose.yml file using scp
cd docker/mysite
# start the app and mysql containers defined in the mysite/docker-compose.yml
docker-compose up -d
To view the site on staging, update your systems hosts
file to direct local.vm.mysite.com
requests to the staging server IP address. For example:
172.10.10.10 local.vm.mysite.com
Load the site in a browser and install WordPress, for example, http://local.vm.mysite.com.
Data Migration
Once your WordPress site is installed, you may want to restore the data from another mysql volume. Perhaps your dev server has the data you now want on your staging instance of WordPress.
1. Perform a mysql dump to get the data from the running mysql container on the dev server. For example, using the development environment from part one, our container is named my_wordpress_project_mariadb
.
# get the mysql container name by listing all of the containers
docker ps -a
# dump the mysql data into the current directory
# from the running docker container named
# my_wordpress_project_mariadb
docker exec my_wordpress_project_mariadb /usr/bin/mysqldump -u root --password=password wordpress > wordpress.sql
2. Prepare your dev server mysql dump for loading into the staging server. Open the wordpress.sql
file in a code editor and replace all instances of the host:port with the staging server host. For example, replace dev.docker.mysite.com:8000
with local.vm.mysite.com
.
3. Upload the updated wordpress.sql
file to the staging server using scp
.
4. ssh
into the staging server and load the wordpress.sql
into the running mysite mysql container.
# get the mysql container name by listing all of the containers
docker ps -a
# load the mysql data from the current directory
# into the running mysite_mysql_1 docker container
cat wordpress.sql | docker exec -i mysite_mysql_1 /usr/bin/mysql -u root --password=changeme! wordpress
After loading a new Docker image, you will need to remove the pre-existing app volume before bringing up the app container for the new image. Use
docker volume ls
to list the volumes anddocker volume rm
to remove the app image. For example,docker volume rm mysite_app
.
That’s it!
Part 2 of 2 in the WordPress from Development to Production using Docker series.