Install WordPress with Docker

Docker WordPress Production Deployment

This tutorial provides a practical guide for Docker WordPress production deployment. You will learn how to deploy automatically WordPress on line using docker compose.

The installation tool kit include:

  • Nginx server, reverse-proxy and letsencrypt for HTTPS certificates
  • WordPress files
  • MariaDB/MySQL used for WordPress database
  • phpMyAdmin interface to connect to your MySQL database
  • WP-Cli: WordPress Command Line Interface
  • Makefile directives for automatization.


Contents:

Prerequisites

Step 1. Create websites directories

Read more: Create a website directory and set up proper permissions

# 0. settings
web_dir=/srv/www
myusername=kassambara
# 1. Create the website directory
sudo mkdir -p $web_dir
# 2. set your user as the owner
sudo chown -R $myusername $web_dir
# 3. set the web server as the group owner
sudo chgrp -R www-data $web_dir
# 4. 755 permissions for everything
sudo chmod -R 755 $web_dir
# 5. New files and folders inherit 
# group ownership from the parent folder
chmod g+s $web_dir

Step 2. Download a nginx-proxy web server template for hosting multiple websites on the same server

# Download a nginx-proxy template
web_dir=/srv/www
git clone https://github.com/kassambara/nginx-multiple-https-websites-on-one-server $web_dir

# Update nginx.tmpl: Nginx configuration file template
rm -rf $web_dir/nginx-proxy/nginx.tmpl
curl -s https://raw.githubusercontent.com/jwilder/nginx-proxy/master/nginx.tmpl> $web_dir/nginx-proxy/nginx.tmpl

# Remove unnecessary files and folders
cd $web_dir
rm -rf your-website-one.com your-website-two.com README.Rmd .gitignore .Rbuildignore .git

The downloaded nginx-proxy folder contains a docker-compose.yml file. This will launch three services:

  • nginx: the nginx-reverse proxy, uses the default nginx image. The label is needed so that the letsencrypt container knows which nginx proxy container to use.
  • nginx-gen: uses the jwilder/docker-gen image. Its command instruction will render a nginx configuration (based on nginx.tmpl) for each website / container added to the network.
  • nginx-letsencrypt: generates and renew the HTTPS certificates. Read more: How to Host Multiple HTTPS Websites on One Server.

All these services are bound to the nginx-proxy network.

Step 3. Download a WordPress docker-compose template

Download a template from Github at: kassambara/wordpress-docker-compose

# Download a WordPress docker-compose template and
# put it in a folder with the same name as your domain name
your_domain_name=www.example.com
cd $web_dir
git clone https://github.com/kassambara/wordpress-docker-compose $your_domain_name

# Change the online docker-compose file name
cd $your_domain_name
mv docker-compose-onlinehost.yml docker-compose.yml

# Remove unnecessary files and folders
rm -rf .git .gitignore

Template directory tree:

www/www.example.com
├── LICENSE
├── Makefile
├── README.md
├── config
│   └── php.conf.ini
├── docker-compose.yml
├── mysql
├── wordpress
├── wp-auto-config.yml
└── wpcli
    ├── Dockerfile
    ├── Makefile
    └── entrypoint.sh

Essential folders:

  • mysql: MySQL database files for MariaDB
  • wordpress: WordPress web files
  • wpcli contains a Dockerfile example to build WordPress CLI.

Essential files:

  • setup-onlinehost.sh: Automatically set online production environment variables.
  • .env file: contain the environment variables required for the wordpress installation
  • docker-compose.yml: WordPress docker compose application services
  • Makefile: Set of simple bash command lines to build, install and configure WordPress, as well as, to start and stop the docker containers.

Step 4. Inspect your web directory

Your web directory should look like this:

www
├── README.md
├── nginx-proxy
│   ├── certs
│   ├── conf.d
│   ├── docker-compose.yml
│   ├── html
│   ├── nginx.tmpl
│   └── vhost.d
└── www.example.com
    ├── LICENSE
    ├── Makefile
    ├── README.md
    ├── config
    ├── docker-compose.yml
    ├── mysql
    ├── wordpress
    ├── wp-auto-config.yml
    └── wpcli

Step 5. Edit the WordPress Docker setup environment variables

# 1. Open the setup file
nano $web_dir/$your_domain_name/setup-onlinehost.sh

# 2. Change these settings as you want 
project_name="wordpress"
user_name="wordpress"
pass_word="wordpress"
email="your-email@example.com"
website_title="My Blog"
website_url="https://www.example.com"
phmyadmin_url="sql.example.com"
env_file=".env"
compose_file="docker-compose.yml"

# 3. Execute: 
chmod +x setup-onlinehost.sh && ./setup-onlinehost.sh 

An automatically updated .env file is available to easily set docker-compose variables without having to modify too much the docker-compose.yml configuration file itself.

Open the .env file and update the contents if you want. In our example, the file is located at www/www.example.com/.env

# Open the file
nano $web_dir/$your_domain_name/.env

Contents:

# 1/ Project name -------------------------------------------------
# Must be lower-case, no spaces and no invalid path chars.
# Will be used also as the WP database name
COMPOSE_PROJECT_NAME=wordpress

# 2/ Database user and password -----------------------------------------
# Set non-root database user if wanted (optional)
DATABASE_PASSWORD=password
DATABASE_USER=root

# 3/ For wordpress auto-install and auto-configuration -------------------
WORDPRESS_WEBSITE_TITLE="My Blog"

# URL: Use this for localhost
WORDPRESS_WEBSITE_URL="https://www.example.com"
WORDPRESS_WEBSITE_URL_WITHOUT_HTTP="www.example.com"
WORDPRESS_WEBSITE_POST_URL_STRUCTURE="/blog/%postname%/"

# Website admin identification. Specify a strong password 
WORDPRESS_ADMIN_USER="wordpress"
WORDPRESS_ADMIN_PASSWORD="wordpress"
WORDPRESS_ADMIN_EMAIL="your-email@example.com"

# 4/ Software versions -----------------------------------------------
WORDPRESS_VERSION=latest
MARIADB_VERSION=latest

# 5/ Ports: Can be changed -------------------------------------------
PHPMYADMIN_PORT=8080

# 6/ Volumes on host --------------------------------------------------
WORDPRESS_DATA_DIR=./wordpress

# 7/ Healthcheck availability of host services (mysql and woordpress server)
# Waiting time in second
WAIT_BEFORE_HOSTS=5
WAIT_AFTER_HOSTS=5
WAIT_HOSTS_TIMEOUT=300
WAIT_SLEEP_INTERVAL=60
WAIT_HOST_CONNECT_TIMEOUT=5

# 8/ Used only in online deployement ---------------------------------
WORDPRESS_WEBSITE_URL_WITHOUT_WWW=example.com
PHPMYADMIN_WEBSITE_URL_WITHOUT_HTTP=sql.example.com

Step 6. Edit the docker-compose configuration file

Inspect and update the$web_dir/$your_domain_name/docker-compose.yml file if you want. It contains a container that redirect non-www to www (recommended). If you don’t want this behaviour, just remove the container.

....
# Redirect non-www to www
  redirectnonwww:
    image: cusspvz/redirect
    container_name: ${COMPOSE_PROJECT_NAME}_redirectnonwww
    restart: always
    environment:
      - VIRTUAL_HOST=${WORDPRESS_WEBSITE_URL_WITHOUT_WWW}
      - HTTPS_METHOD=noredirect
      - LETSENCRYPT_HOST=${WORDPRESS_WEBSITE_URL_WITHOUT_WWW}
      - LETSENCRYPT_EMAIL=${WORDPRESS_ADMIN_EMAIL}
      - REDIRECT=${WORDPRESS_WEBSITE_URL}
      # CHANGE THE REDIRECT URL
      - REDIRECT=https://www.example.com
      - WORKER_CONNECTIONS=1024
    networks:
      - ${COMPOSE_PROJECT_NAME}_default
      - nginx-proxy
.....

Step 7. Run the nginx reverse proxy

# 1. Create the docker network. Do this once
docker network create nginx-proxy

# 2. Create the reverse proxy with the 
# nginx, nginx-gen and nginx-letsencrypt containers
cd $web_dir/nginx-proxy/
docker-compose up -d

Step 8. Allow users to post large documents or images

In the Nginx configuration file, you need also to increase client_max_body_size to allow users to post large documents. You can add for example the line client_max_body_size 64M; in the server{} directive.

# 1. Create a configuration file for your domain
# in the nginx-proxy vhost folder
nano $web_dir/nginx-proxy/vhost.d/$your_domain_name

# 2. Add this to allow the upload of 64M
client_max_body_size 64M;

One single command to do the above operation:

echo 'client_max_body_size 64M;' > nano $web_dir/nginx-proxy/vhost.d/$your_domain_name

Step 9. Install WordPress using docker compose

Two methods are available for installing and configuring your WordPress web site:

  1. Automatic installation + manual configuration
  2. Automatic installation + automatic configuration

Method 1. Automatic installation + manual configuration

Automatic installation of WordPress in docker

Three lines of docker-compose commands:

  1. Build docker application images
  2. Start wordpress installation in detached mode
  3. (Health)Check the availability of WordPress docker services

Go into your domaine name folder and type this:

cd $your_domain_name
docker-compose build
docker-compose up -d 
docker-compose run --rm healthcheck

Explaining the different docker compose options:

  • -d: start containers in detached options
  • --rm: remove containers when stopped

Alternatively, you can also use the following make shortcut commands. Easy to use on Unix operating systems (MAC and Linux)

cd $your_domain_name
make install

Console logs look like this:

Console logs

Manual WordPress configuration

Navigate your browser to www.example.com and follow the installation prompts

  1. Set WordPress language

Select WordPress language

  1. Create an administrative user

Create an administrative user

  1. Success

Installation success

  1. Log in as the administrative user

Login as admin

  1. Admin dashboard

Admin dashbord

Method 2. Automatic installation and configuration

Before, re-trying the installation, first clean up everything as follow:

docker-compose down
rm -rf mysql/* wordpress/*

The following docker-compose or make commands can be used to automatically install and configure wordpress.

Using the docker-compose commands.

# Build docker images and start up wordpress
docker-compose up -d --build
# Automatic wordpress configuration
docker-compose -f docker-compose.yml -f wp-auto-config.yml run --rm wp-auto-config

Using the make commands. For Unix systems (MAC and Linux) users:

make autoinstall

Step 10. Access to your website

  1. Visit your wordpress website at www.example.com. Default identification for admin (www.example.com/wp-login.php):
    • Username: wordpress and
    • Password: wordpress

Website

Once your site is running you can begin to create and publish any content you’d like in your WordPress instance.

  1. Visit your database via phpMyAdmin at http://sql.example.com
    • Username: root and
    • Password: password

phpMyAdmin

Shutdown and cleanup

This section present useful set of commands to know.

  1. Shutdown WordPress docker containers and dependencies. The command docker-compose down removes the containers and default network, but preserves your WordPress database.
# Stop and remove containers
docker-compose down
  1. (Re)start WordPress docker compose containers
docker-compose up -d
  1. Reset or reinitialize everything
  • Stop and remove containers
  • Remove related wordpress and mysql installed files
docker-compose down
rm -rf mysql/* wordpress/*

Note that, instead of using the above docker-compose commands, you can also use easily the following make shortcut command lines if you have Unix systems (MAC / Linux).

# Build, and start the wordpress website
make start
# Stop and remove wordpress docker containers
make down
# Reset everything
make reset

Summary

This tutorial provides a practical guide for Docker WordPress production deployment.



Version: Français

WordPress Local Development Using Docker Compose (Prev Lesson)
(Next Lesson) Using Docker WordPress Cli to Manage WordPress Websites
Back to Install WordPress with Docker

Comments ( 8 )

  • Aysenur BURAK

    Hello, I am trying set up wordpress on docker for my domain name.
    I did all steps but I receive blank screen on web site. In step 9 it says “wordpress: 80 now available” instead of “nginx: 80 now available”. I need your help.

  • Charles

    This was an awesome tutorial….. Much appreciated!!

  • Cito Giulini

    fantastic. how can I force to remove www?

  • Jean Ibbotson

    You are the BEST!!! All I had to do was keep clicking to find the thing I need. Thanks a million 🙂

    • Alboukadel

      Thank you so much for the positive feedback, highly appreciated!

  • Chris Nash

    Some remarks:
    Projekt_name must be set to “wordpress”
    Quotation marks should be added in value of WORDPRESS_WEBSITE_URL_WITHOUT_HTTP in .env.
    First REDIRECT in docker-compose.yml in redirectnonwww needs to be commented out, because of duplicate error.

  • Jacobo Tapia

    This is not working. The browser always says that it can’t trust my certificate. I don’t know what else to do here.

    I spent the entire night trying to figure out how to deploy.

  • Jacobo Tapia

    This works for http, but https doesn’t work at all.

    I created this script to maker easier all the process.

    #!/bin/bash

    web_dir=/src/www
    myusername=root
    domain_name=domain.subdomain.com

    genoteca_folder=/src/www/$domain_name

    nginx_proxy_repo=https://github.com/kassambara/nginx-multiple-https-websites-on-one-server
    nginx_folder=/src/www/nginx-multiple-https-websites-on-one-server/nginx-proxy
    final_nginx_folder=/src/www/nginx-proxy

    echo —INSTALL REQUIRED COMPONENTS—-
    sudo apt update
    sudo apt install apt-transport-https ca-certificates curl software-properties-common
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add –
    sudo add-apt-repository “deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable”
    sudo apt update
    apt-cache policy docker-ce
    sudo apt install docker-ce docker-compose git
    sudo systemctl status docker

    echo —CREATE AND GIVE PERMISSIONS TO WEBSITES DIR—-
    sudo mkdir -p $web_dir
    # 2. set your user as the owner
    sudo chown -R $myusername $web_dir
    # 3. set the web server as the group owner
    sudo chgrp -R www-data $web_dir
    # 4. 755 permissions for everything
    sudo chmod -R 755 $web_dir
    # 5. New files and folders inherit
    # group ownership from the parent folder
    chmod g+s $web_dir

    echo —INSTALL NGINX PROXY—-
    git clone $nginx_proxy_repo $web_dir
    rm -rf $web_dir/nginx-proxy/nginx.tmpl
    curl -s https://raw.githubusercontent.com/jwilder/nginx-proxy/master/nginx.tmpl > $web_dir/nginx-proxy/nginx.tmpl
    cd $web_dir
    rm -rf your-website-one.com your-website-two.com README.Rmd .gitignore .Rbuildignore .git README.md

    echo —INSTALL WORDPRESS—-
    cd $web_dir
    git clone https://github.com/kassambara/wordpress-docker-compose $domain_name

    echo —CONFIGURE DOCKER COMPOSE FOR ONLINEHOST—-
    cd $genoteca_folder
    mv docker-compose-onlinehost.yml docker-compose.yml

    echo —FINAL TOUCHES—-
    cd $genoteca_folder
    vi ./setup-onlinehost.sh
    chmod +x setup-onlinehost.sh && ./setup-onlinehost.sh
    vi .env
    vi docker-compose.yml

    cd $final_nginx_folder
    cd vhost.d
    echo “client_max_body_size 64M;” > $domain_name
    cd $final_nginx_folder
    docker network create nginx-proxy
    docker-compose up -d

    cd $genoteca_folder
    docker-compose up -d –build
    docker-compose -f docker-compose.yml -f wp-auto-config.yml run –rm wp-auto-config

    I don’t do the non-www to www. I remove the container from the docker-compose.yml

Give a comment

Want to post an issue with R? If yes, please make sure you have read this: How to Include Reproducible R Script Examples in Datanovia Comments

Teacher
Alboukadel Kassambara
Role : Founder of Datanovia
Read More