🐳 Docker Debugging Deep Dive: Fixing Port Conflicts, Volumes & Networking in a Django + MySQL + NGINX Setup

paritosh patiparitosh pati
3 min read

Recently, I ran into a Docker-related issue that looked deceptively simple — but turned into a valuable deep-dive into container networking, volume persistence, and real-world troubleshooting.

Here’s a breakdown of what happened, how I debugged it, and what I learned.


🧩 The Stack

I was containerizing a basic full-stack app using:

  • Django (backend API)

  • MySQL (relational database)

  • NGINX (reverse proxy)

The app was orchestrated using Docker Compose, with each service defined as a container.


❌ The Problem

When I spun up my containers, everything seemed to build just fine — until the deployment hit a wall with this error:

bashCopyEditError starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use

In short: NGINX was trying to bind to port 80, but something else was already using it.


🛠️ The Fixes — Step by Step

1. 🔍 Solving the Port Conflict

This was the first and most immediate blocker. I found that my host machine already had a service (probably Apache or another NGINX instance) using port 80.

✅ Solution:

  • Either stop the conflicting service, or

  • Change the NGINX container’s exposed port in the docker-compose.yml:

yamlCopyEditports:
  - "8080:80"  # Now maps container port 80 to host port 8080

2. 🧹 Cleaning Up Residual MySQL Data

Even after restarting containers, MySQL was acting strangely — failing on startup with data-related errors.

✅ Solution:

  • Removed the old volume storing MySQL data.

  • Re-created the volume externally to decouple lifecycle from containers.

bashCopyEditdocker volume rm my_mysql_data
docker volume create my_mysql_data

Then updated docker-compose.yml:

yamlCopyEditvolumes:
  - my_mysql_data:/var/lib/mysql

3. 🌐 Creating a Custom Docker Bridge Network

To ensure all services could talk to each other reliably (especially NGINX to Django, and Django to MySQL), I created an external bridge network.

bashCopyEditdocker network create notes-app-nw

Then added this to the Compose file:

yamlCopyEditnetworks:
  default:
    external:
      name: notes-app-nw

This ensured all containers shared a common network with static naming.


🧪 Final Result

After these changes, I re-ran:

bashCopyEditdocker-compose up --build

And this time — everything just worked. ✅

  • MySQL initialized with a fresh schema.

  • Django connected cleanly to the database.

  • NGINX reverse-proxied requests to Django on the internal network.


💡 Key Takeaways

  • Port 80 errors are common — always double-check what’s running on your host.

  • Volumes persist across container restarts — don’t forget to clean or isolate them when debugging.

  • Custom Docker networks make multi-container setups more predictable and secure.

  • Docker is powerful but requires systems thinking — it’s not just about code, it’s about configuration and infrastructure.


🧠 Final Thoughts

This was a great exercise in real-world Docker troubleshooting. It reminded me that debugging container issues isn’t just about error messages — it’s about understanding how your services interact, persist data, and expose themselves to the outside world.

If you’ve faced a similar issue — or have tips for handling Docker networking and volumes — drop a comment or share your experience!

0
Subscribe to my newsletter

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

Written by

paritosh pati
paritosh pati