Module 09 / Project 03 — Docker Compose¶
Home: README
Learn Your Way¶
| Read | Build | Watch | Test | Review | Visualize | Try |
|---|---|---|---|---|---|---|
| — | This project | — | — | Flashcards | — | — |
Focus¶
Using docker-compose.yml to run a multi-service stack: app + database, with networking, volumes, and environment variables.
Why this project exists¶
Real applications rarely run alone. They need databases, caches, queues, and other services. Docker Compose lets you define all these services in a single file and start them together with one command. Docker Compose also creates a private network so your services can find each other by name. This project teaches you to orchestrate a FastAPI application with a PostgreSQL database.
Run¶
cd projects/modules/09-docker-deployment/03-docker-compose
# Start both services (web app + database)
docker compose up --build
Docker Compose will:
- Build the web service image from the Dockerfile.
- Pull the
postgres:16image from Docker Hub (first time only). - Create a private network for both services.
- Start the database, then start the web app.
Once you see Uvicorn running on http://0.0.0.0:8000, visit:
- http://127.0.0.1:8000 — root endpoint
- http://127.0.0.1:8000/docs — interactive API docs (try creating items here)
- http://127.0.0.1:8000/items — list all items
Create some data¶
Use the /docs page or curl:
# Create an item
curl -X POST http://127.0.0.1:8000/items \
-H "Content-Type: application/json" \
-d '{"name": "Widget", "description": "A useful widget"}'
# List all items
curl http://127.0.0.1:8000/items
Stop the services¶
# Stop containers (data is preserved in the volume)
docker compose down
# Stop containers AND delete the database volume
docker compose down -v
Expected output¶
Visiting http://127.0.0.1:8000 returns:
After creating an item, GET /items returns:
Alter it¶
- Add a
DELETE /items/{item_id}endpoint that removes an item from the database. Rebuild withdocker compose up --build. - Add a
redis:7service todocker-compose.yml. You do not need to connect it to the app yet -- just get it running alongside the other services. - Change the database port mapping from
"5432:5432"to"5433:5432"and connect to it from your host on port 5433.
Break it¶
- Change the
DATABASE_URLin the web service's environment to use the wrong hostname (e.g.,wronghostinstead ofdb). What error do you get? - Remove the
volumessection entirely. Rundocker compose up, create some items, thendocker compose downanddocker compose upagain. Are the items still there? Why not? - Remove
depends_on: - dbfrom the web service. Rundocker compose up. Does the web service start before the database is ready?
Fix it¶
- Restore
dbas the hostname. Docker Compose registers each service name as a DNS hostname on the shared network. - Restore the
volumessection. Without a named volume, PostgreSQL stores data inside the container's filesystem, which is destroyed when the container is removed. - Restore
depends_on. While it does not guarantee the database is ready, it ensures the database container starts first.
Explain it¶
- How does the web service find the database using the hostname
db? What creates this DNS entry? - What is a named volume? Where does Docker store the actual data on disk?
- What happens to the data when you run
docker compose downvsdocker compose down -v? - Why do the
POSTGRES_USER,POSTGRES_PASSWORD, andPOSTGRES_DBvalues need to match theDATABASE_URL?
Mastery check¶
You can move on when you can:
- write a
docker-compose.ymlwith two services from scratch, - explain how Docker networking connects services by name,
- demonstrate that data persists across restarts with named volumes,
- describe what
depends_ondoes and does not guarantee.
Related Concepts¶
Next¶
Continue to 04-ci-github-actions.