# Docker Compose ## Real applications are rarely just one container A web app usually needs a database, maybe a cache, maybe a background worker — several containers that need to be created, networked together, and started in a sensible order. Doing this manually with individual `docker run` commands works, but gets tedious and error-prone fast, especially remembering the exact flags every time. ## One file, the whole application **Docker Compose** describes an entire multi-container application in one YAML file: ```yaml services: web: image: nginx:alpine ports: - "8080:80" depends_on: - api api: image: my-api:1 ``` - **`services`** — each entry is one container, using the exact same concepts (image, ports, etc.) you already know from plain `docker run`. - **`depends_on`** — controls STARTUP order (api starts before web) — note this ensures order, not that the dependency is fully READY yet, a subtlety real applications often need extra handling for. - **Networking is automatic** — Compose creates a shared network for all services in the file by default, so `web` can reach `api` by name immediately, no manual `docker network create` needed. ## The commands ``` docker compose up -d # start every service defined in the file, in the background docker compose ps # see the status of every service docker compose logs # see logs from every service, or docker compose logs docker compose down # stop and remove everything Compose created ``` ## Compose doesn't replace anything you've learned — it automates it Every Compose service maps directly onto a `docker run` command you could write by hand; Compose just describes the whole set declaratively in one file instead of remembering and re-typing several long commands correctly, every time, in the right order. ## Instructor Notes **Lesson goal:** Frame Compose as automation of already-understood concepts, not new magic — students should be able to mentally translate a `services:` block back into individual `docker run` commands. **Approximate timing:** 15 minutes read; 10 minutes live. **Common misconception to watch for:** treating `depends_on` as "waits until fully healthy" — it only controls START order, not readiness; worth flagging as a real, common source of race conditions in actual production Compose files. **Discussion question:** "Why might describing your application declaratively in one file be better than a shell script that runs several `docker run` commands in sequence?" (Good answer: reviewable, versionable, and Compose itself understands the relationships between services, rather than just blindly executing a sequence.)