Docker Series — Part 5: Deploying WordPress with MySQL in Containers (With Persistent Storage & Linking)

Nitin DhimanNitin Dhiman
3 min read

Welcome back to the Docker: Basics to Advance series.
In Part 5, we're going hands-on with a real-world, production-like scenario — deploying WordPress with a MySQL backend inside Docker containers using persistent storage and multi-tier architecture principles.

What Is WordPress?

WordPress is a powerful PHP-based content management system (CMS) used for blogs and websites. It stores all post and user data in a MySQL database, making it a perfect candidate for a three-tier architecture:

USER → WebApp (WordPress) → Database (MySQL)

Step 1: Pulling Required Docker Images

We'll need two Docker images:

  • WordPress (Web application)

  • MySQL (Database)

docker pull wordpress
docker pull mysql

Step 2: Launch the MySQL Database Container

WordPress requires a running database. Let’s launch it with environment variables:

docker run -dit --name db \
-e MYSQL_ROOT_PASSWORD=test@123\
-e MYSQL_DATABASE=mydb \
-e MYSQL_USER=nitin\
-e MYSQL_PASSWORD=test@321\
mysql:latest

This sets up a MySQL container with:

  • DB name: mydb

  • User: nitin

  • Password: test@321

Step 3: Launch the WordPress Container

Next, let’s run WordPress and expose it on port 8080:

docker run -dit --name mywp -p 8080:80 wordpress:latest

Now, open your browser and visit:
http://<your-host-ip>:8080

Follow the setup wizard and connect WordPress to the database with:

  • DB Name: mydb

  • Username: nitin

  • Password: test@321

  • Database Host: IP of the MySQL container (docker inspect db)

If the IP of the MySQL container changes, WordPress will lose connection. We'll fix this later using container linking.

Step 4: Make Your Database Storage Persistent

By default, data in a container is ephemeral. If the MySQL container is deleted, so is your data. Let’s fix that:

✅ Create a Volume Directory:

mkdir /mydata

✅ Run MySQL with Volume Mount:

docker run -dit --name db \
-e MYSQL_ROOT_PASSWORD=test@123\
-e MYSQL_DATABASE=mydb \
-e MYSQL_USER=nitin\
-e MYSQL_PASSWORD=test@321\
-v /mydata:/var/lib/mysql \
mysql:latest

Now all database files are stored on your host system inside /mydata.

Even if the container is removed, your data will persist.

Step 5: Reconnect WordPress with the Persistent Database

Re-launch the WordPress container and link it with the new persistent MySQL container:

docker run -dit --name mywp -p 8080:80 --link db wordpress:latest

Now during setup, use:

  • DB Host: db (container name, not IP)

This is called Container Linking — instead of relying on changing IPs, you connect using container names.


Understanding Container Linking

When you use --link db, Docker maps the container name db to its IP internally. This ensures WordPress always connects to the right container, even if the IP changes.

But linking has limitations:

  • It’s one-way only

  • Still internally IP-based — not scalable for microservices or orchestration

For more flexibility in future, we'll explore Docker Compose or custom Docker networks in upcoming posts.


Key Docker Concepts in This Blog

ConceptExplanation
-eSets environment variables inside container
-vMounts host directory as volume
--linkLinks one container to another using name
docker inspectShows container’s IP, ports, mounts
docker rm -f <name>Force remove a container
docker psList running containers
/var/lib/mysqlDefault data path for MySQL

You’ve now built a multi-container architecture entirely in Docker — like a mini production system running in your terminal.

Got questions about linking containers or persistent volumes? Drop a comment or ping me — I’d love to help!

0
Subscribe to my newsletter

Read articles from Nitin Dhiman directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Nitin Dhiman
Nitin Dhiman

Self-taught DevOps enthusiast on a journey from beginner to pro. Passionate about demystifying complex tools like Docker, AWS, CI/CD & Kubernetes into clear, actionable insights. Fueled by curiosity, driven by hands-on learning, and committed to sharing the journey. Always building, always growing 🚀