Wordpress containerization using Docker and Nginx

by Adam Świątkowski
5 mins read
Wordpress inside Docker

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.

Wordpress and Docker together
Wordpress and Docker together

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:

Wordpress and Docker project structure
Wordpress and Docker 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!

Wordpress installation
Wordpress installation

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.

Related Articles

This website uses cookies to improve your experience. I'll assume you're ok with this, but you can opt-out if you wish. Read Privacy Policy. Accept