How to Dockerize wordpress website

So I decided to start Site Monki blog where I will be sharing on updates, announcements from Site Monki product and how-tos around web monitoring, performance and security. I think beyond the application, this content will add more value to Site Monki users.

I decided that the product blog should be a subdirectory under the sitemonki domain at sitemonki.com/blog. The URL structure has direct benefits in SEO but also I don’t have to create a subdomain just to run a blog. I have decided to go with WordPress because it’s a really fantastic CMS I have used for years.

Running sitemonki.com/blog means I have to run the blog on the same server as the Site Monki App. The main App is already on Docker containers, so I thought it wise to run WordPress on Docker containers too. This way, I don’t really change anything on the host server. Plus I have the added benefit of easily deploying, backing up and migrating both services easily when they are containerized.

First thing we need is a reverse proxy. This will route HTTP requests from web browser to corresponding services. Nginx is an excellent choice.

 NGINX configuration for reverse proxying is quite easy to follow and you can read more on the official site but the part we are interested in is this;

# proxy configures 
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-HTTPS-Protocol $ssl_protocol;
proxy_set_header X-NginX-Proxy true;

# wordpress service
location /blog {
    proxy_pass http://127.0.0.1:5050;
}

We are really forwarding the remote IP, hostname, http protocol scheme (http or https) to the WordPress container which exposes port 5050. Nginx will reverse proxies all requests to Apache running inside the WordPress container we shall talk about shortly.

Now comes the interesting part; running WordPress as a container. I assume you already have some basic knowledge of Docker and how to install it. If you don’t, then Docker website has some really good documentation you can follow.

I use docker-compose to define services we need to run WordPress. First is the database service which we run from Mysql 5.7 image. I run a healthcheck to ensure that MySQL container is running before other services that depend on it start. Without this check, WordPress will start and complain that it can’t connect to the database. The MySQL container is attached to a docker named volume sm_blog_mysql_data so we don’t lose our data on container rebuilds.

Then I also use the official WordPress container. The default tag comes with PHP 7.1 and Apache. We define WordPress Host, User, Password and DB name as environment variables. More variables are supported and you can find out more on the image page on docker hub.

Also notice that I am syncing the whole wordpress folder from the host server at /home/dave/blog/ to the wordpress container at /var/www/html/blog. This is because containers are ephemeral which means data is lost once the container is rebuilt or deleted. To prevent that and enable easy changes to the wordpress site, I use Docker unnamed volume which you can read about here.

docker-compose.yml file below defines all these services. All I have to do now is run “docker-compose up” command to bring up the site which is accessible at https://sitemonki.com/blog.

version: '2.1'
services:
  wordpress:
    image: wordpress
    restart: always
    ports:
      - 5050:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: example
      WORDPRESS_DB_PASSWORD: example
      WORDPRESS_DB_NAME: example
    volumes:
      - /home/dave/blog/:/var/www/html/blog
    depends_on:
      db:
        condition: service_healthy

  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: example
      MYSQL_USER: example
      MYSQL_PASSWORD: example
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    healthcheck:
      test: ["CMD", "mysqladmin", "-u$MYSQL_USER", "-p$MYSQL_PASSWORD",  "ping", "-h", "localhost"]
      timeout: 20s
      retries: 10
    volumes:
      - sm_blog_mysql_data:/var/lib/mysql

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    ports:
      - 8282:80
    restart: always
    environment:
      MYSQL_USERNAME: example
      MYSQL_ROOT_PASSWORD: example
      PMA_HOST: db
      PMA_PORT: 3306
      PMA_ARBITRARY: 1
    volumes:
      - /sessions
    depends_on:
      db:
        condition: service_healthy
volumes:
  sm_blog_mysql_data:

Bonus but optional container is phpmyadmin which I use to view, create and delete records on the wordpress database. I Simply have to open 8282, the port it’s running on via the firewall and access it as sitemonki.com:8282.

So that’s it. If I choose to move the site to another host, I simply have to git pull the codebase from github or wherever and then run “docker-compose up” after install Nginx on the host server. That’s really a breeze and that’s the advantage of Docker containers.

Leave a Reply

Your email address will not be published. Required fields are marked *