If you’ve ever dealt with WordPress, you’ve probably noticed that it’s not the fastest software out of the box. This is not inherently a problem with WordPress, as it is a complex app that runs on a cross platform technology. Performance of WordPress though can be improved with the combined effects of several small tweaks.
This guide will walk through a recipe for setting up WordPress with Docker containers an tuning those containers to maximize the performance of WordPress. For the sake of simplicity, it’s assumed that you’re at least familiar with WordPress and Docker, and you have a machine with Docker already running on it. If not, there are many ways you can get Docker. For a guide to migrating content to Docker, check out this post here.
One of the fundamentals though for running a performant WordPress install is to have a good host. I use Microsoft Azure for my websites, and they are rather speedy. The machine itself doesn’t have to be beefy. A single core box can handle sites that get thousands of hits per day without a problem, and they don’t cost a fortune either.
The basic architecture for this recipe is to use three containers to host the site.
In addition to the performance gains from NGINX and PHP FPM turning on WP Total Cache will give an extra boost in performance too.
With any container, it’s always a good idea to store persistent data outside of the container. This is basically anything that you can’t stand to lose. In the context of WordPress, this would be your configuration files, custom themes, images and other media, and the database.
docker network create wp-net
mkdir /docker && cd /docker
mkdir www && cd www
wget https://wordpress.org/latest.zip && unzip latest.zip
Then, rename the wordpress folder html.
mv wordpress html
mkdir html
MySQL is pretty easy to setup. We’ll setup a folder on the host machine and mount that folder as a volume in the Docker container.
mkdir database
docker run --name mysql --restart always -v /docker/database:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=yourpassword --net wp-net -d mysql
docker exec -i wp-mysql mysql -u root --password=yourpassword <<< "CREATE DATABASE wpdb;"
Then, import the data. Again, don’t forget to use the correct password. Note: the path to the .sql file from the dump is on the host computer, not a path in the container.
docker exec -i wp-mysql mysql -u root --password=yourpassword wintellectcomwp < /path/to/your/wp.sql
Setting up the PHP-FPM container is pretty straightforward. It just requires mapping the www folder you already created earlier to the appropriate place in the container so that PHP-FPM can find the php file. This particular container is using PHP 7 with FPM which performs better than previous versions of PHP such as 5.6 or 5.7.
docker run -dit --name fpm --restart always --net wp-net -v /docker/www:/var/www/ wordpress:4.8-php7.1-fpm
The NGINX setup is probably the most complicated because it requires setting up two configuration files and mounting the www folder and these two files in the container.
mkdir nginx && cd nginx
user root;
# Set this to the number of CPU cores available to your computer.
worker_processes 2;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types text/html text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
include /etc/nginx/conf.d/*.conf;
}
map $sent_http_content_type $expires {
default off;
text/html epoch;
text/css max;
application/javascript max;
~image/ max;
}
server {
listen 80;
server_name www.yourdomain.com;
root /var/www/html;
index index.php;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ .php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_pass fpm: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 ~* .(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
}
}
docker run --name nginx -dit --restart always --net wp-net -v /docker/nginx/nginx.conf:/etc/nginx/nginx.conf -v /docker/nginx/default.conf:/etc/nginx/conf.d/default.conf -v /docker/www:/var/www/ -p 80:80 nginx
Now, all the containers are running, but there’s a few random things left to do.
chown -R www-data:www-data /docker/www/*
/** MySQL database */
define('DB_NAME', 'wpdb');
/** MySQL database username */
define('DB_USER', 'root');
/** MySQL database password */
define('DB_PASSWORD', 'yourpassword');
/** MySQL hostname */
define('DB_HOST', 'mysql');
I’ve used this recipe on a number of sites and all of them load rather quickly. You can verify the results of your website by looking at performance metrics on www.webpagetest.org Most of my sites get “Straight A’s” with this recipe.
Also, while Docker isn’t required, it does make setting up many of these software packages easier because they are already preconfigured. The same principles can be applied to a VM for optimal performance too.
Microsoft Azure and Amazon Web Services (AWS) are two of the most popular cloud platforms.…
Cloud management is difficult to do manually, especially if you work with multiple cloud…
Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…
https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…
FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…
Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…