Deploying WordPress with MySQL, Redis, and NGINX on Docker
Tags: wordpress, mysql, nginx, docker
Published: 2024-03-27 13:05:42

---
title: Deploying WordPress with MySQL, Redis, and NGINX on Docker
published: true
tags: WordPress,MySQL, NGINX, Docker
canonical_url: https://firstfinger.in/wordpress-mysql-redis-nginx/
---

 ![Deploying WordPress with MySQL, Redis, and NGINX on Docker](https://firstfinger.in/content/images/2024/03/WordPress-with-MySQL--Redis--and-NGINX-on-Docker.jpg)

WordPress is a popular content management system (CMS) that powers millions of websites worldwide. However, as your website grows, you may experience performance issues. To improve WordPress performance, you can use object caching, which stores frequently accessed data in memory, reducing the number of database queries.

**Prerequisites:**

- [Basic knowledge of Docker](https://firstfinger.in/kubernetes-vs-docker-swarm/) and Docker Compose
- [Docker](https://docs.docker.com/engine/install/) & [Docker Compose](https://docs.docker.com/compose/install/linux/) installed on your machine
- A domain name or IP address pointing to your server

## Why do we need better performance in WordPress?

Website performance is crucial for user experience and search engine optimization (SEO). A slow website can lead to a high bounce rate, meaning visitors leave your site without interacting. Additionally, search engines like Google consider website speed as a ranking factor.

## What does Object Cache do in WordPress?

WordPress, by default, caches internal application objects like breadcrumbs and menu items in the MySQL database. This can be taxing since the database also handles queries for page requests, potentially increasing website load times.

[Object caching is a technique used to store frequently accessed data in memory, reducing the number of database queries.](https://firstfinger.in/why-redis-is-fast/) In WordPress, object caching is disabled by default. When a user requests a page, if the data is already cached in Redis, it is served directly from the cache, bypassing the database. This significantly reduces response times and [improves the overall performance of your WordPress site](https://firstfinger.in/self-hosting-vs-managed-hosting-wordpress/).

## Why Use Redis for Object Caching?

Redis is an open-source, [in-memory data store that can be used as a database](https://firstfinger.in/in-memory-caching-vs-in-memory-data-store/), cache, and message broker.

**Compared to alternatives like Memcached, Redis offers:**

- Persistent data storage
- Data replication and high availability
- Richer data structures like lists, hashes, and sets
- Better performance for WordPress object caching

## WordPress with MySQL Database and Redis as Object Cache with NGINX Reverse Proxy on Docker

We'll use Docker Compose to orchestrate a multi-container setup

## Step 1: Create a Docker Compose file

Create a new file named `docker-compose.yml` in your project directory and add the following code:

```
version: '3'
services:
  wordpress:
    image: wordpress:latest
    ports:
      - "8080:80" # Change port
    restart: always
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepassword
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - wordpress:/var/www/html
    depends_on:
      - db
      - redis

  db:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepassword
      MYSQL_ROOT_PASSWORD: rootpassword
    volumes:
      - db:/var/lib/mysql

  redis:
    image: redis:alpine
    restart: always

volumes:
  wordpress:
  db:

```

_docker-compose.yml_

1. This Docker Compose file creates three services: `WordPress`, `MySQL`, and `Redis`. 
2. The WordPress service uses the latest WordPress image and connects to the MySQL service using the environment variables defined in the file. 
3. The MySQL service uses version 8.0 of the MySQL image, and the Redis service uses the Redis Alpine image. 
4. The WordPress data is persisted in the `wordpress` directory for easy access.
5. Run `docker-compose up -d` to start the containers.
6. You can access your WordPress site by visiting the URL `http://your-server-ip:8080`

> 💡 Follow Steps No. 5/6 to set up the domain name & SSL certificate for your WordPress site. 

## Step 2: Accessing the WordPress Container Shell

To edit the changes in the WordPress config file we need to access the container shell, to do that follow:

![Deploying WordPress with MySQL, Redis, and NGINX on Docker](https://firstfinger.in/content/images/2024/03/006221cd217fd6a7b7c08fe26ef51f6c.png)

1. Run `docker ps` to see running container details such as name, ID, status etc, and get WordPress container ID.
2. Use the command `docker exec -it <container_id> /bin/bash` to access the WordPress container. 
3. Run this command in the WordPress container shell: `apt update && apt upgrade -y && apt install nano`. This command will update the system packages and install the **Nano text editor** in the shell.

## Step 3: Add Redis Configuration to wp-config.php

1. Now run `nano wp-config.php` to edit the code in the WordPress container shell & add the following code on top of the code in wp-config.php 

![Deploying WordPress with MySQL, Redis, and NGINX on Docker](https://firstfinger.in/content/images/2024/03/a391095eaf0ce204e148c77f5670ddb4.png)

```
define ( 'WP_CACHE', true);
```

1. Add the following lines to enable Redis object caching:

![Deploying WordPress with MySQL, Redis, and NGINX on Docker](https://firstfinger.in/content/images/2024/03/dc9c4bc64ffde63a3873c5ce97a93595.png)

```
define('WP_REDIS_HOST', 'redis');
define('WP_REDIS_PORT', '6379');
define('WP_CACHE_KEY_SALT', 'your-domain-name');

```

1. Replace `your-domain-name` with your actual `domain name`.
2. Confirm & press `Ctrl + X` then `Shift + Y` to save the changes.

## Step 4: Install the Redis Object Cache Plugin

To enable object caching in WordPress, you need to install and activate the Redis Object Cache plugin.

![Deploying WordPress with MySQL, Redis, and NGINX on Docker](https://firstfinger.in/content/images/2024/03/6820c1351e5bbae87ca9232a1cb986b1.png)

![Deploying WordPress with MySQL, Redis, and NGINX on Docker](https://firstfinger.in/content/images/2024/03/a2fc23ebdb35e7ce5eb0469598c6dc27.png)

![Deploying WordPress with MySQL, Redis, and NGINX on Docker](https://firstfinger.in/content/images/2024/03/c999b3a4300c8a33bbf7ffaa187c5849.png)

![Deploying WordPress with MySQL, Redis, and NGINX on Docker](https://firstfinger.in/content/images/2024/03/d4dffb4689c2965e4ff86b6ef1427982.png)

## Step 5: Run NGINX Reverse Proxy Manager Container

The reverse proxy acts as a gateway, routing external traffic to your Docker containers while providing additional features like SSL termination, load balancing, and caching, making it easier to manage and secure your containerized applications.

```
version: '3.8'
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '80:80'
      - '81:81'
      - '443:443'
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
```

_NGINX Proxy Manager with SQLite Database_

> **OR**

```
version: '3.8'
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '80:80'
      - '443:443'
      - '81:81'
    environment:
      DB_MYSQL_HOST: "db"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "npm"
      DB_MYSQL_PASSWORD: "npm"
      DB_MYSQL_NAME: "npm"
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    depends_on:
      - db

  db:
    image: 'jc21/mariadb-aria:latest'
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: 'npm'
      MYSQL_DATABASE: 'npm'
      MYSQL_USER: 'npm'
      MYSQL_PASSWORD: 'npm'
      MARIADB_AUTO_UPGRADE: '1'
    volumes:
      - ./mysql:/var/lib/mysql

```

_NGINX Proxy Manager with MariaDB as Database_

> 💡 Choose **SQLite for lightweight** , single-user, or embedded applications, while **MariaDB is a better fit for multi-user environments** , web applications, and scenarios requiring advanced database features and scalability.

1. Save the above content to a file named `docker-compose.yml` in a new directory.
2. Open a terminal, navigate to the directory with the `docker-compose.yml` file.
3. Run `docker-compose up -d` to start the containers in detached mode.
4. Let's Encrypt SSL certificates are stored in `./letsencrypt` the directory.
5. Access the [Nginx Proxy Manager](https://nginxproxymanager.com/) GUI admin interface at `http://your_server_ip:81`
6. Default Admin Login :

```
Email: admin@example.com
Password: changeme
```

_NGINX Proxy Manager Default Login Credentials_

## Step 6: Setting up WordPress with NGINX Reverse Proxy

![Deploying WordPress with MySQL, Redis, and NGINX on Docker](https://firstfinger.in/content/images/2024/03/image-6.png)

1. Click on "Hosts" > "Add Proxy Host"
2. Enter the following details:
  - **Domain Names** : Enter your WordPress site's domain name (e.g., example.com)
  - **Scheme** : Choose "http://" unless you have a valid SSL certificate for your domain
  - **Forward Hostname / IP** : Enter the IP address of your WordPress container (e.g., 172.17.0.3)
  - **Forward Port** : Enter the port your WordPress container is listening on (usually 80)
3. Click on "Save" to create the proxy host
4. If you want to **enable SSL** with a Let's Encrypt certificate:
  - Click on the proxy host you just created
  - Go to the "SSL" tab section
  - Check the "Force SSL" & "HTTP/2" box
  - Choose "Request a new SSL Certificate" by entering a valid email then save.
5. Your WordPress site should now be accessible via the Nginx Proxy Manager, with a valid SSL Certificate.

## Step 7: Backing Up WordPress Site

To ensure data safety, it's essential to regularly back up your WordPress site.

[**UpdraftPlus** is a popular backup plugin](https://wordpress.org/plugins/updraftplus/) that simplifies and automates this process. It supports backup to remote storage like Dropbox, Google Drive and affordable paid add-ons.

![Deploying WordPress with MySQL, Redis, and NGINX on Docker](https://firstfinger.in/content/images/2024/03/image-7.png)

![Deploying WordPress with MySQL, Redis, and NGINX on Docker](https://firstfinger.in/content/images/2024/03/image-8.png)

You can take a manual backup or set automated schedules daily or after every hour.

This setup provides a robust and efficient environment for your WordPress site, improving both performance and data security.

## 10 Tips for improving WordPress site performance

### 1. Use a Content Delivery Network (CDN)

A CDN is a network of servers that delivers static content like images, videos, and CSS files from the server closest to the user's location. By using a CDN, you can reduce the load on your server and improve website speed. Popular CDN providers include Cloudflare, Amazon CloudFront, and MaxCDN.

### 2. Enable Cloudflare Caching

Cloudflare is a popular CDN and web application firewall that offers caching and performance optimization features. By enabling Cloudflare caching, you can store frequently accessed data on Cloudflare's servers, reducing the number of requests to your server. This can significantly improve website speed and reduce server load.

### 3. Optimize Images

Large images can slow down your website. Therefore, it's essential to optimize images for the web by compressing them and using the correct file format. You can use image optimization plugins like WP Smush or ShortPixel to optimize images automatically. These plugins can also lazy load images, which means they only load when they're visible on the screen.

### 4. Minimize HTTP Requests

Each file on your website, such as images, CSS, and JavaScript files, requires an HTTP request to load. By minimizing the number of HTTP requests, you can improve website speed. You can use plugins like Autoptimize to minify and combine CSS and JavaScript files, reducing the number of requests required to load your website.

### 5. Use a Caching Plugin

Caching plugins like W3 Total Cache or WP Super Cache can improve website speed by caching frequently accessed data and serving it from the cache instead of generating it dynamically. These plugins can also minify HTML, CSS, and JavaScript files, reducing the size of the files and improving website speed.

### 6. Enable Gzip Compression

Gzip compression reduces the size of files sent from your server to the user's browser, reducing the amount of data transferred and improving website speed. You can enable Gzip compression using a plugin like WP Rocket or by adding code to your .htaccess file.

### 7. Disable Unused Plugins and Themes

Unused plugins and themes can slow down your website and pose security risks. Therefore, it's essential to disable and delete any plugins and themes that you're not using. This can improve website speed and reduce security risks.

### 8. Use a Fast Web Host

The speed of your website depends on the speed of your web host. Therefore, it's essential to choose a fast and reliable web host that can handle your website's traffic. Look for a web host that offers fast load times, good uptime, and reliable customer support.

### 9. Optimize Database

Over time, your WordPress database can become cluttered with unused data, such as post revisions, spam comments, and transient options. By optimizing your database, you can improve website speed and reduce database size. You can use plugins like WP-Optimize or WP-Sweep to optimize your database.

### 10. Use a Lightweight Theme

A lightweight theme with minimal features and optimized code can improve website speed. Therefore, it's essential to choose a lightweight theme that's optimized for performance. Look for a theme that's well-coded, fast-loading, and responsive.

By implementing these tips, you can improve the performance of your WordPress site and provide a better user experience.