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.
- Networking in Compose — How Compose creates networks and how service discovery works
- Compose file: networks — The
networkskey in a Compose file - Bridge network driver — How bridge networks isolate containers and provide DNS resolution
- Compose file: services — Service configuration including
environment,healthcheck,depends_on - Environment variables in Compose — How to set and manage env vars
- docker network inspect — Inspect a network to see which containers are connected
Setup
cd week-03/labs/lab-02-network-debugging/starterYou have:
docker-compose.yml— The broken Compose fileapi/— A simple Python API that talks to the databasefrontend/— An nginx config that proxies to the API
Start the Broken Stack
docker compose up -d --buildConfirm It's Broken
curl localhost:8080
curl localhost:8080/api/itemsThe 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:
- frontend — nginx reverse proxy, listens on port 80, forwards
/api/toapi:5000 - api — Python Flask app, connects to
db:3306, serves JSON - 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 psAll 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 shInside 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
exitIf 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 shInside 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"
exitIf 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-netLook 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.confWhat 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):
- Which services are on which networks? See Compose file: networks
- Do all services that need to talk share a network? See Networking in Compose
- Do the hostnames in environment variables match actual service names? See Environment variables in Compose
- Do the ports in the nginx config match what the API actually listens on?
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/healthPart 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/healthBonus 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:
- Symptom — What error did you see?
- Root cause — What was wrong in the configuration?
- Fix — What did you change?
- How you found it — Which debugging command revealed the issue?
Checkpoint ✅
Before moving on, verify:
- All three services are running and healthy
-
curl localhost:8080returns the frontend page -
curl localhost:8080/api/itemsreturns 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 -vNext Lab
Continue to Lab 3: Development Workflow
