The "Why" Behind the Project
As someone transitioning into DevOps, I quickly realized that real learning happens through building, not just watching tutorials. While I had previously set up WordPress using manual SSH commands and Ansible playbooks, I kept hearing about containerization as a fundamental DevOps skill. I decided to bridge this gap by completing Project 1 in my 30-project DevOps roadmap: containerizing a full WordPress LEMP stack.
This post documents my hands-on journey, the challenges I faced, and the key concepts I learned along the way.
What I Built
I created a production-like WordPress environment that can be spun up with a single command:
docker-compose up -d
This command launches two containers:
MySQL 8.4 for the database
WordPress with PHP 8.3 for the application
The entire infrastructure is defined in a docker-compose.yml file—Infrastructure as Code in practice.
The Architecture: Simple but Powerful
Here's how the pieces fit together:
User Browser → Localhost:8080 → WordPress Container → MySQL Container (db:3306)
The magic happens in the docker-compose.yml:
services:
db:
image: mysql:8.4
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- db_data:/var/lib/mysql
wordpress:
image: wordpress:latest
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
WORDPRESS_DB_NAME: wordpress
depends_on:
- db
volumes:
- wp_data:/var/www/html
volumes:
db_data:
wp_data:
Key Challenges & Solutions
Challenge 1: Database Connection Issues
Problem: WordPress installation failed with "database connection error"
Solution: I learned that containers communicate via service names, not localhost. The fix was using db (the service name in docker-compose.yml) as the database host during WordPress setup.
Challenge 2: Port Conflicts on Mac
Problem: Port 80 was already in use
Solution: Changed the port mapping to "8080:80" in the docker-compose.yml file
Challenge 3: Authentication Errors with GitHub
Problem: Couldn't push code due to password authentication deprecation
Solution: Generated a GitHub Personal Access Token and used it for command-line Git operations
What This Project Taught Me
1. Infrastructure as Code (IaC) Isn't Just a Buzzword
Defining my entire stack in a YAML file felt revolutionary. This single file can:
Be version controlled
Be shared with team members
Deploy identical environments everywhere
Serve as documentation
2. Container Networking Is Magical (Once You Understand It)
The concept that wordpress container can connect to db container using just the service name (db:3306) clicked for me. Docker creates a virtual network where containers can discover each other by name.
3. Development-Production Parity Is Achievable
With this setup, I can run the exact same environment on:
My local MacBook
An AWS EC2 instance
A CI/CD pipeline
Any developer's machine
No more "it works on my machine" problems!
4. Learning in Public Has Benefits
Documenting this journey on GitHub and writing this post helped solidify my understanding. The complete code is available here for anyone to reference or build upon.
Comparison: Before vs. After Docker
| Aspect | Manual/Ansible Setup | Dockerized Setup |
|---|---|---|
| Setup Time | 15-20 minutes | 30 seconds |
| Reproducibility | Environment-dependent | Guaranteed consistency |
| Learning Curve | Lower initially | Steeper but more valuable |
| Portability | Server-specific | Runs anywhere with Docker |
| Scaling | Manual intervention | Add more containers |
Essential Commands I Lived By
Start everything
docker-compose up -d
Check status
docker-compose ps
View logs
docker-compose logs -f
Stop everything
docker-compose down
Stop and remove volumes (clean slate)
docker-compose down -v
Access MySQL shell
docker-compose exec db mysql -u root -p
For Beginners: My Recommended Learning Path
If you're starting with Docker, here's what worked for me:
Start with the official Docker getting-started tutorial - Builds confidence
Containerize something simple (like a static website) before tackling databases
Use Docker Compose early - It simplifies multi-container apps
Don't fear
docker-compose down -v- Starting fresh often fixes issuesRead error messages carefully - They're usually helpful
Next Steps in My Journey
This project is just the beginning. Next, I plan to:
Add Nginx as a reverse proxy for better performance and SSL termination
Implement persistent storage properly for uploads and themes
Add monitoring with a Prometheus/Grafana container
Create a CI/CD pipeline to automatically build and deploy the image
Convert this to Kubernetes manifests to learn orchestration
Final Thoughts
Dockerizing WordPress transformed from a daunting task to an empowering skill. The initial frustration with networking and configuration gave way to excitement as I realized the power of containers.
The most valuable lesson wasn't about Docker specifically, but about the DevOps mindset: automate everything, document thoroughly, and build reproducible systems.
To anyone on a similar learning journey: start building. Your first project doesn't need to be perfect; it needs to be finished. Then write about it, share it, and start the next one.
Resources that helped me:
Connect with me:
- GitHub: @alanvarghese-dev
Top comments (0)