DEV Community

Alan Varghese
Alan Varghese

Posted on

From Manual Setup to One-Command Deployment: My Journey Dockerizing WordPress

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:

  1. MySQL 8.4 for the database

  2. 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:

  1. Start with the official Docker getting-started tutorial - Builds confidence

  2. Containerize something simple (like a static website) before tackling databases

  3. Use Docker Compose early - It simplifies multi-container apps

  4. Don't fear docker-compose down -v - Starting fresh often fixes issues

  5. Read error messages carefully - They're usually helpful

Next Steps in My Journey

This project is just the beginning. Next, I plan to:

  1. Add Nginx as a reverse proxy for better performance and SSL termination

  2. Implement persistent storage properly for uploads and themes

  3. Add monitoring with a Prometheus/Grafana container

  4. Create a CI/CD pipeline to automatically build and deploy the image

  5. 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:

Top comments (0)