Wordpress is one of the most popular CMS written in PHP. WP is not too difficult to run in a remote or local environment using LAMP stack, however in a containerized environment Wordpress can play tricks. Docker and its benefits are more and more often present in modern IT environments. That’s why we will try to combine the advantages of Docker and Wordpress, creating a containerized Blog environment.
Table of Contents
Do you remember setting up Laravel using Laradock inside Docker container? If you need a repeat, go here.
What are we going to build?
Let’s start by discussing what our architecture will look like.
“On top” we will start the Nginx web server / proxy. Its task will be to redirect the traffic from the outside to the inside of our WP container.
“Underneath” we will run a slightly modified Wordpress official docker image. WP will be working under subdirectory example.com/blog/, that’s why I’ve said that docker with WP can be tricky, we need to remember this 😎. Why under example.com/blog/ subdirectory? Because it’s more “SEO friendly” than starting the blog.example.com subdomain. Of course, we’re assuming that the homepage of example.com has the main portal and the blog section it contains will be managed by Wordpress.
First of all we have to install nginx. Here are commands to achieve this:
sudo su -
apt-get update
apt-get install nginx-full
Remember to allow out connections for ports 80 and 443 in your favourite firewall.
Then create or modify default nginx server block. Here’s my example:
nano /etc/nginx/sites-enabled/default
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name _;
client_max_body_size 50M;
ssl_certificate /etc/letsencrypt/live/XXX.XX/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/XXX.XX/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
location /blog/ {
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-Proto $scheme;
proxy_pass http://127.0.0.1:8081;
proxy_redirect off;
}
location / {
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-Proto $scheme;
proxy_pass http://127.0.0.1:8082;
proxy_redirect off;
}
}
Check if everything is ok using below command:
nginx -t
And if so, restart nginx:
service nginx restart
In this article we won’t touch the example.com main portal, we will focus only on WP things.
Let’s dockerize it!
Here’s my project structure:
Firstly let’s see my .env file:
WORDPRESS_THEME=twentynineteen
WORDPRESS_DB_HOST=szj3dii-db-wp
WORDPRESS_DB_USER=dbwp
WORDPRESS_DB_PASSWORD=12345678
WORDPRESS_DB_NAME=dbwp
MYSQL_ROOT_PASSWORD=12345678
MYSQL_USER=dbwp
MYSQL_USER_PASSWORD=12345678
MYSQL_DB_NAME=dbwp
HTTP_DOMAIN=localhost
Of course, these are just examples! In production environments, they must be properly secured!
Secondly please take a look at my Dockerfile:
FROM wordpress:latest
ENV WORDPRESS_THEME=$WORDPRESS_THEME
RUN apt-get clean
RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y \
nano \
sudo \
curl \
&& rm -r /var/lib/apt/lists/*
RUN curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
RUN php wp-cli.phar --info
RUN chmod +x wp-cli.phar
RUN mv wp-cli.phar /usr/local/bin/wp
WORKDIR /var/www/html
RUN usermod -u 1000 www-data
RUN chown -R www-data:www-data /var/www/html
EXPOSE 80
ENTRYPOINT sudo -E -u www-data -- wp theme activate ${WORDPRESS_THEME} && sudo -E -u www-data -- wp plugin update --all && sudo -E -u www-data -- wp core update && apache2-foreground
This Dockerfile uses standard Wordpress Docker image, however, I’ve included WP-CLI inside WP container. WP-CLI is the command-line interface for WordPress. You can update plugins, configure multisite installations and much more, without using a web browser.
Thirdly let’s take a look at my docker-compose.yml file:
version: '3.3'
networks:
szj3dii_network:
services:
szj3dii-wp:
depends_on:
- szj3dii-db-wp
build:
context: .
dockerfile: ./Dockerfile
ports:
- "127.0.0.1:8081:80"
restart: always
environment:
WORDPRESS_THEME: $WORDPRESS_THEME
WORDPRESS_DB_HOST: $WORDPRESS_DB_HOST
WORDPRESS_DB_USER: $WORDPRESS_DB_USER
WORDPRESS_DB_PASSWORD: $WORDPRESS_DB_PASSWORD
WORDPRESS_DB_NAME: $WORDPRESS_DB_NAME
WORDPRESS_CONFIG_EXTRA: |
define('WP_HOME', 'https://example.com/blog/');
define('WP_SITEURL', 'https://example.com/blog/');
$$_SERVER['REQUEST_URI'] = str_replace("/wp-admin/", "/blog/wp-admin/", $$_SERVER['REQUEST_URI']);
$$_SERVER['REQUEST_URI'] = '/blog' . $$_SERVER['REQUEST_URI'];
volumes:
- ./wordpress:/var/www/html
networks:
- szj3dii_network
szj3dii-db-wp:
image: mysql:5.7
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
MYSQL_DATABASE: $MYSQL_DB_NAME
MYSQL_USER: $MYSQL_USER
MYSQL_PASSWORD: $MYSQL_USER_PASSWORD
HTTP_DOMAIN: $HTTP_DOMAIN
volumes:
- /var/lib/mysql
- ./mysql-dump:/docker-entrypoint-initdb.d
ports:
- "127.0.0.1:3316:3306"
networks:
- szj3dii_network
Remember to change example.com and blog to appropriate for your needs. You can create mysql-dump directory and place there WP SQL dump if you have one, it’ll be uploaded to DB automatically at first start of DB container, also create the blank directory inside project directory called wordpress.
Lastly let’s start our project using:
docker-compose up -d --build --force-recreate
Dockerized Wordpress in subdirectory?
Most importantly, here’s the trick for the above problem, place it inside wp-config.php (in dockerized environment skip this point, because these entries will be automatically included using the WORDPRESS_CONFIG_EXTRA variable in the docker-compose.yml file):
define('WP_HOME', 'https://example.com/blog/');
define('WP_SITEURL', 'https://example.com/blog/');
$_SERVER['REQUEST_URI'] = str_replace("/wp-admin/", "/blog/wp-admin/", $_SERVER['REQUEST_URI']); $_SERVER['REQUEST_URI'] = '/blog' . $_SERVER['REQUEST_URI'];
That’s all!
In conclusion, you should now see the standard WP installation page (or if you’ve migrated DB dump – homepage of your blog). I hope now you will easily set up a containerized environment with Docker, Nginx and Wordpress.