WordPress is an open-source CMS that allows users to create a website or blog easily. Deploying a WordPress website to production is a challenging task, and it requires a lot of configuration and optimization. Docker and Kubernetes are two popular technologies that can help simplify the process of deploying WordPress to production.
In this blog post, we will show you how to deploy a production-grade WordPress website using Docker and Kubernetes. We will cover the following topics:
Prerequisites
- Setting up a MySQL database
- Setting up WordPress with Docker Compose
- Creating a Docker image for WordPress
- Deploying WordPress to Kubernetes
Prerequisites
Before we start, make sure you have the following:
- Docker installed on your machine.
You can use Docker Desktop for your initial level of testing and that can be downloaded free of cost from the Downloads page.
- Kubernetes installed and configured.
You can either use Kubernetes under Docker Desktop for your initial testing or preferrably use any of Cloud providers like AKS, EKS and GKE. Choose as per your convenience.
- A domain name for your WordPress website.
- Basic knowledge of Docker and Kubernetes.
If you’re completely new to Docker and Kubernetes, refer to this and this link.
Setting up a MySQL database
The first step in deploying a WordPress website is to set up a MySQL database. To set up a MySQL database in Kubernetes, we will create a Kubernetes deployment and service.
Create a file called mysql-deployment.yaml and add the following contents:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.7
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: yourpassword
- name: MYSQL_DATABASE
value: wordpress
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
---
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- name: mysql
port: 3306
targetPort: 3306
selector:
app: mysql
This YAML file creates a deployment and service for the MySQL database. It uses the official MySQL Docker image and sets the MySQL root password and database name using environment variables. It also creates a persistent volume claim to store the MySQL data.
To create the MySQL deployment and service, run the following command:
$ kubectl apply -f mysql-deployment.yaml
Setting up WordPress with Docker Compose
Now that we have a MySQL database running in Kubernetes, we can set up WordPress using Docker Compose. Docker Compose is a tool for defining and running multi-container Docker applications.
Create a file called docker-compose.yaml and add the following contents:
version: '3.7'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: yourpassword
MYSQL_DATABASE: wordpress
wordpress:
depends_on:
- db
image: wordpress:5.7.2-fpm-alpine
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: yourpassword
WORDPRESS_DB_NAME: wordpress
volumes:
- ./wp-content:/var/www/html/wp-content
volumes:
db_data:
This YAML file creates two services:
-
db: This service uses the official MySQL Docker image and sets the MySQL root password and database name using environment variables. It also creates a volume for storing the MySQL data.
-
wordpress: This service uses the official WordPress Docker image and sets the database hostname, username, password, and database name using environment variables. It also creates a volume for storing the WordPress content.
To start the WordPress and MySQL containers using Docker Compose, run the following command:
$ docker-compose up -d
Creating a Docker image for WordPress
Now that we have WordPress running with Docker Compose, we can create a Docker image for WordPress that includes all the required plugins, themes, and configuration.
Create a file called Dockerfile in the root directory of your WordPress installation and add the following contents:
FROM wordpress:5.7.2-fpm-alpine
# Install required PHP extensions
RUN apk add --no-cache \
php7-mysqli \
php7-curl \
php7-gd \
php7-intl \
php7-mbstring \
php7-soap \
php7-xml \
php7-xmlrpc \
php7-zip \
php7-opcache
# Copy custom configuration files
COPY php.ini /usr/local/etc/php/
COPY wp-config.php /var/www/html/
COPY custom-entrypoint.sh /usr/local/bin/
# Set permissions
RUN chmod +x /usr/local/bin/custom-entrypoint.sh
ENTRYPOINT ["custom-entrypoint.sh"]
CMD ["php-fpm"]
This Dockerfile installs the required PHP extensions and copies the custom configuration files. It also sets the entrypoint to a custom script that runs the required database migrations and configurations.
Create a file called custom-entrypoint.sh in the root directory of your WordPress installation and add the following contents:
#!/bin/sh
# Wait for the database to be ready
until wp db check --allow-root; do
sleep 1
done
# Run the database migrations
wp db upgrade --allow-root
# Configure WordPress settings
wp option update siteurl "http://your-domain.com" --allow-root
wp option update home "http://your-domain.com" --allow-root
wp option update blogname "Your WordPress Site Title" --allow-root
wp option update blogdescription "Your WordPress Site Description" --allow-root
wp option update timezone_string "Your WordPress Timezone" --allow-root
wp option update permalink_structure "/%postname%/" --allow-root
# Activate plugins and themes
wp plugin activate your-plugin --allow-root
wp theme activate your-theme --allow-root
exec docker-entrypoint.sh "$@"
This script waits for the database to be ready, runs the required database migrations, and configures the WordPress settings. It also activates the required plugins and themes.
To build the Docker image, run the following command:
$ docker build -t your-registry/your-image:latest .
Replace your-registry and your-image with your Docker registry and image name.
Deploying WordPress to Kubernetes
Now that we have a Docker image for WordPress, we can deploy it to Kubernetes.
Create a file called wordpress-deployment.yaml and add the following contents:
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
spec:
selector:
matchLabels:
app: wordpress
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: wordpress
spec:
containers:
- name
- name: wordpress
image: your-registry/your-image:latest
ports:
- containerPort: 9000
env:
- name: WORDPRESS_DB_HOST
value: "mysql"
- name: WORDPRESS_DB_USER
valueFrom:
secretKeyRef:
name: mysql
key: username
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysql
key: password
- name: WORDPRESS_DB_NAME
valueFrom:
configMapKeyRef:
name: wordpress
key: database_name
volumeMounts:
- name: wordpress-content
mountPath: /var/www/html/wp-content
volumes:
- name: wordpress-content
persistentVolumeClaim:
claimName: wordpress-content
apiVersion: v1
kind: Service
metadata:
name: wordpress
spec:
selector:
app: wordpress
ports:
name: http
port: 80
targetPort: 9000
type: LoadBalancer
This YAML file defines a Deployment and a Service for WordPress. The Deployment specifies the container image and environment variables, and also mounts the wordpress-content
volume. The Service exposes the WordPress container using a LoadBalancer.
Create a file called mysql-deployment.yaml
and add the following contents:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql
key: password
- name: MYSQL_DATABASE
valueFrom:
configMapKeyRef:
name: wordpress
key: database_name
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-data
---
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
selector:
app: mysql
ports:
- name: mysql
port: 3306
targetPort: 3306
This YAML file defines a Deployment and a Service for MySQL. The Deployment specifies the container image and environment variables, and also mounts the mysql-data volume. The Service exposes the MySQL container using a ClusterIP.
Create a file called wordpress-content-pvc.yaml and add the following contents:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wordpress-content
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
This YAML file defines a PersistentVolumeClaim for storing the WordPress content.
Create a file called mysql-data-pvc.yaml and add the following contents:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
This YAML file defines a PersistentVolumeClaim for storing the MySQL data.
Finally, we need to apply the YAML files to our Kubernetes cluster. Run the following commands in your terminal:
$ kubectl apply -f wordpress-config.yaml
$ kubectl apply -f wordpress-deployment.yaml
$ kubectl apply -f mysql-deployment.yaml
$ kubectl apply -f wordpress-content-pvc.yaml
$ kubectl apply -f mysql-data-pvc.yaml
This will create the necessary Kubernetes objects for deploying WordPress using Docker.
Once the objects have been created, you can check their status by running the following commands:
$ kubectl get configmap wordpress
$ kubectl get secret mysql
$ kubectl get pvc
$ kubectl get deployment
$ kubectl get pod
$ kubectl get service
If everything is working correctly, you should see output that indicates the objects are running and available.
To access WordPress, you can use the external IP address of the WordPress service. You can get this address by running the following command:
$ kubectl get service wordpress
This will output the external IP address of the WordPress service. You can use this IP address to access WordPress in your web browser.
Conclusion
In this blog post, we have shown you how to deploy a production-grade WordPress instance using Docker and Kubernetes. We have walked you through the process of creating Docker images for WordPress and MySQL, as well as the necessary Kubernetes objects for deploying WordPress.
By following these steps, you can create a scalable and reliable WordPress deployment that is easy to manage and maintain. We hope that this blog post has been useful for you and has given you a good understanding of how to deploy WordPress using Docker and Kubernetes