In today’s cloud-native era, deploying applications in containers is a must-have skill especially for dynamic websites like WordPress. In this tutorial, you’ll learn how to deploy a WordPress website using Docker, push the container image to AWS Elastic Container Registry (ECR), and run it on Amazon EKS (Elastic Kubernetes Service).
This approach gives you scalability, resilience, and performance for your WordPress site — while using modern DevOps practices.
Let’s dive into the full step-by-step guide!
Prerequisites
Before starting, make sure you have:
An AWS Account
AWS CLI configured (
aws configure)Docker installed
kubectlinstalled and configuredeksctlinstalledBasic knowledge of Docker and Kubernetes
Step 1: Dockerize Your WordPress Application
First, let’s create a Docker file for frontend wordpress

Similarly, Create Docker file for backend WordPress which means for MySQL

Now, Create docker-compose file
- We are using docker compose to build and run wordpress website in localhost

Basically, we have created a Dockerfile for both WordPress and MySQL, along with a Docker Compose file to build the docker images and run the containers locally. This allows us to verify that the website is working properly before deploying it to the cloud.
Now, Build Images using docker compose
docker compose build
Verify your images
docker images
Run docker container Multi Copy Code Blocks
docker compose up -d

After successfully run the container go to browser and paste URL
- http://localhost:8080/

Step 2: Push Your Docker Images to AWS ECR
Prerequisites
- Configure AWS CLI
- Set a AWS region and acoount
Set AWS region and AWS account Multi Copy Code Blocks
AWS_REGION=us-east-1
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
To verifying Multi Copy Code Blocks
ehco $AWS_REGION
echo $AWS_ACCOUNT_ID
Now, create ECR repositories in AWS for both wp-frontend and wp-mysql. Multi Copy Code Blocks
# For WordPress
aws ecr create-repository --repository-name wp-frontend --region $AWS_REGION
# For Mysql
aws ecr create-repository --reposiroty-name wp-backend --region $AWS_REGION

Login to AWS ECRMulti Copy Code Blocks
aws ecr get-login-password -–region $AWS_REGION | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com
Now tag your images to push to AWS ECRMulti Copy Code Blocks
# Tag for WordPress-frontend
docker tag cloudwithyuvi/wp-frontend:latest ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/wp-frontend:latest
# tag for Mysql-Backend
docker tag cloudwithyuvi/wp-backend:8.0 ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/wp-backend:8.0
Push the wordpress- frontend images in AWS ECR
Multi Copy Code Blocks
docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/wp-frontend:latest

Push the mysql-backend images in AWS ECR Multi Copy Code Blocks
docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/wp-backend:8.0

You can verify your images in AWS ECR
- Go to AWS Console and click on ECR
- Click on your repository and you will find your images

Step 3: Deploy WordPress to AWS EKS using ECR Images
Prerequisites
- Configure AWS CLI
- Set a AWS region and acoount
- Install kubectl
- Install eksctl
- Install Helm
Install kubectl
Multi Copy Code Blocks
curl -o kubectl https://amazon-eks.s3.us-west-2.amazonaws.com/1.30.0/2024-06-14/bin/linux/amd64/kubectl
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin
kubectl version --client
Install eksctl
Multi Copy Code Blocks
curl --silent --location "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
sudo mv /tmp/eksctl /usr/local/bin
eksctl version
Now, create ECR repositories in AWS for both wp-frontend and wp-mysql.
Multi Copy Code Blocks
# For WordPress
aws ecr create-repository --repository-name wp-frontend --region $AWS_REGION
# For Mysql
aws ecr create-repository --reposiroty-name wp-backend --region $AWS_REGION
Now, create role for EC2
- Go to AWS Console —> click on IAM
- Click on role tab and create
- Use Case: EC2
- Attach Policies
- AmazonEKSWorkerNodePolicy
- AmazonEC2ContainerRegistryReadOnly
- AmazonEKS_CNI_Policy
- Role Name: EKSNodeRole
Attach Policy to nodegroup to access EBS volume
Multi Copy Code Blocks
aws iam attach-role-policy --role-name --policy-arn arn:aws:iam::aws:policy/AmazonEBSCSIDriverPolicy
Now, create AWS EKS cluster
Multi Copy Code Blocks
eksctl create cluster \
--name wordpress-cluster \
--region ap-south-1 \
--nodegroup-name wordpress-nodes \
--node-type t3.medium \
--nodes 2 \
--nodes-min 2 \
--nodes-max 4 \
--managed
Note: It will take 10-15 min to create AWS EKS Cluster. You can take tea break 😂😂

Update Kubeconfig
Multi Copy Code Blocks
aws eks --region ap-south-1 update-kubeconfig --name wordpress-cluster
Verifying and get nodes
Multi Copy Code Blocks
kubectl get nodes

Install EBS CSI Driver [ For Storage ]Multi Copy Code Blocks
eksctl create iamserviceaccount --name ebs-csi-controller-sa --namespace kube-system --cluster wordpress-cluster --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy --approve --role-only --role-name AmazonEKS_EBS_CSI_DriverRole
Enable Driver from Console
aws eks create-addon --cluster-name wordpress-cluster --addon-name aws-ebs-csi-driver --service-account-role-arn arn:aws:iam:::role/AmazonEKS_EBS_CSI_DriverRole
Verify DriverMulti Copy Code Blocks
kubectl get pods -n kube-system | grep ebs
Now, Create Menifest file for deploy wordpress
For namespace.yml
Multi Copy Code Blocks
apiVersion: v1
kind: Namespace
metadata:
name: wordpress
Apply namespace.yml
Multi Copy Code Blocks
kubectl apply -f namespace.yaml
For wordpress-pvc.yml
Multi Copy Code Blocks
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wp-pv-claim
namespace: wordpress
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
storageClassName: gp2
Apply wordpress-pvc.yml
kubectl apply -f wordpress-pvc.yml
For mysql-pvc.yml
Multi Copy Code Blocks
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wp-pv-claim
namespace: wordpress
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
storageClassName: gp2
Apply mysql-pvc.yml Multi Copy Code Blocks
kubectl apply -f mysql-pvc.yml
For wordpress-deployment.ymlMulti Copy Code Blocks
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
namespace: wordpress
spec:
replicas: 2
selector:
matchLabels:
app: wordpress
template:
metadata:
labels:
app: wordpress
spec:
containers:
- image: .dkr.ecr.ap-south-1.amazonaws.com/:latest
name: wordpress
env:
- name: WORDPRESS_DB_HOST
value: mysql.wordpress.svc.cluster.local:3306
- name: WORDPRESS_DB_USER
value: wpuser
- name: WORDPRESS_DB_PASSWORD
value: wppassword
- name: WORDPRESS_DB_NAME
value: wordpress
ports:
- containerPort: 80
volumeMounts:
- name: wp-persistent-storage
mountPath: /var/www/html
volumes:
- name: wp-persistent-storage
persistentVolumeClaim:
claimName: wp-pv-claim
Apply wordpress-deployment.yml
kubectl apply -f wordpress-deployment.yml
For wordpress-service.yml
Multi Copy Code Blocks
apiVersion: v1
kind: Service
metadata:
name: wordpress-service
namespace: wordpress
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: wordpress
Apply wordpress-service.ymlMulti Copy Code Blocks
kubectl apply -f wordpress-service.yml
For mysql-deployment.yml
Multi Copy Code Blocks
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
namespace: wordpress
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:8.0
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: rootpassword
- name: MYSQL_DATABASE
value: wordpress
- name: MYSQL_USER
value: wpuser
- name: MYSQL_PASSWORD
value: wppassword
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
Apply mysql-deployment.yml Multi Copy Code Blocks
kubectl apply -f mysql-deployment.yml
For mysql-servcie.yml
Multi Copy Code Blocks
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: wordpress
spec:
ports:
- port: 3306
selector:
app: mysql
clusterIP: None
Apply mysql-servcie.yml Multi Copy Code Blocks
kubectl apply -f mysql-service.yml
Now, Verify persistent volume claim will be bound status
Multi Copy Code Blocks
kubectl get pvc -n wordpress
Verify pods status are runningMulti Copy Code Blocks
kubectl get pods -n wordpress
Copy the external IP for run your website on browserMulti Copy Code Blocks
kubectl get svc -n wordpress

If all are running status then copy the External IP of wordpress-service and paste it on your browser.


