[LAB]

Network Debugging

week-03/labs/lab-02-network-debugging

Course Contents 8 weeks · 45 labs

Lab 2 hero image

Lab 2: Network Debugging

Time: 30 minutes
Objective: Diagnose and fix networking issues in a broken Docker Compose stack


The Scenario

You've been handed a three-tier application: a frontend web server, a backend API, and a database. The Compose file has three networking problems. The application doesn't work. Your job is to find and fix each issue.

Useful Documentation

The answers to every bug in this lab are in the official Docker docs. Get comfortable reading them — this is how you'll solve real problems on the job.


Setup

cd week-03/labs/lab-02-network-debugging/starter

You have:

  • docker-compose.yml — The broken Compose file
  • api/ — A simple Python API that talks to the database
  • frontend/ — An nginx config that proxies to the API

Start the Broken Stack

docker compose up -d --build

Confirm It's Broken

curl localhost:8080
curl localhost:8080/api/items

The static page might load, but the API calls should fail (502 Bad Gateway, connection refused, or timeout). The application is broken. Time to investigate.


Part 1: Map Out the Architecture

Before debugging, understand what the application should look like:

User → :8080 → frontend (nginx) → api:5000 → db:3306 (mysql)

Three services, three hops:

  1. frontend — nginx reverse proxy, listens on port 80, forwards /api/ to api:5000
  2. api — Python Flask app, connects to db:3306, serves JSON
  3. db — MySQL, stores data

Each hop is a potential failure point. Read Networking in Compose to understand how containers on the same network discover each other by service name.


Part 2: Systematic Debugging

Work from the bottom of the stack up. If the database is broken, nothing above it will work.

Check 1: Are All Containers Running?

docker compose ps

All three should show Up. If any are restarting or exited, check their logs first:

docker compose logs <service-name>

Check 2: Can the API Reach the Database?

Get a shell in the API container and test connectivity:

docker compose exec api sh

Inside the container:

# Is DNS working? Can we resolve "db"?
getent hosts db

# Can we reach the database port?
nc -zv db 3306

# What about the hostname the API is configured to use?
echo $DB_HOST
getent hosts $DB_HOST

exit

If getent hosts db works but getent hosts $DB_HOST doesn't, the environment variable is pointing at the wrong hostname.

Check 3: Can the Frontend Reach the API?

docker compose exec frontend sh

Inside the container:

# Can we resolve "api"?
getent hosts api

# Can we reach the API on the port nginx expects?
wget -qO- http://api:5000/health || echo "FAILED on 5000"

exit

If DNS resolution fails, the frontend and API are probably on different networks.

Check 4: Inspect the Networks

# List all networks for this project
docker network ls | grep network-debugging

# Inspect each network to see which containers are on it
docker network inspect starter_frontend-net
docker network inspect starter_backend-net

Look at which containers are connected to which networks. Services can only communicate if they share at least one network. The docs on bridge networks explain why — each user-defined bridge is an isolated network segment with its own DNS resolver. Read the docker network inspect reference to understand the output.

Check 5: Inspect the nginx Config

docker compose exec frontend cat /etc/nginx/conf.d/default.conf

What port is nginx proxying to? Does it match the port the API is listening on?


Part 3: Find and Fix the Issues

Open docker-compose.yml and frontend/nginx.conf. There are three problems across these files. Use the debugging output from Part 2 to guide you.

Hints for what to look for (the docs will help you understand each one):

Fixing

After each fix, restart and test:

docker compose down
docker compose up -d --build

# Test end-to-end
curl localhost:8080
curl localhost:8080/api/items
curl localhost:8080/api/health

Part 4: Verify the Fix

When everything works, you should be able to:

# Frontend serves the page
curl -s localhost:8080

# API returns data through the frontend proxy
curl -s localhost:8080/api/items

# API health check passes
curl -s localhost:8080/api/health

Bonus Verification: Network Isolation

Verify that the frontend cannot directly reach the database (good security practice):

docker compose exec frontend sh -c "nc -zv db 3306 2>&1 || echo 'Good: frontend cannot reach db directly'"

If the frontend can't reach the database, your network segmentation is working correctly. This is the whole point of user-defined bridge networks — read Bridge network driver to understand why the default bridge behaves differently from user-defined bridges.


Part 5: Document Your Findings

For each issue you found, note:

  1. Symptom — What error did you see?
  2. Root cause — What was wrong in the configuration?
  3. Fix — What did you change?
  4. How you found it — Which debugging command revealed the issue?

Checkpoint ✅

Before moving on, verify:

  • All three services are running and healthy
  • curl localhost:8080 returns the frontend page
  • curl localhost:8080/api/items returns JSON data from the database
  • You can explain each networking issue you found
  • You understand why services on different networks can't communicate

Clean Up

docker compose down -v

Next Lab

Continue to Lab 3: Development Workflow