This chapter's application is a workshop signup service: a Flask app in ~/signup that stores names in Postgres.
~/signup
├── app.py Flask app, listens on $PORT (5000), connects to $DB_HOST (db)
├── requirements.txt flask, psycopg
├── Dockerfile FROM python:3.12-slim, pip install, CMD python app.py
└── compose.yamlimage or build
A service needs an image. It either names one or builds one.
services:
db:
image: postgres:16 # pulled from the registry if missing
web:
build: . # docker build with ./ as the contextbuild: . is short for a mapping. Use the long form when the Dockerfile has another name or the context is elsewhere:
build:
context: ./services/web
dockerfile: Dockerfile.prod| You write | Image used | Built when |
|---|---|---|
image: postgres:16 | postgres:16 | never; pulled if missing |
build: . | <project>-<service> | image missing, or --build |
| both | the image: name | as for build:; the result is tagged with image: |
docker compose up builds a missing image once. After that it reuses it, even if app.py changed. Lesson 8 covers rebuilding.
ports
ports is a list of "HOST:CONTAINER" strings, the same format as docker run -p:
ports:
- "8000:5000" # host 8000 → container 5000
- "127.0.0.1:9000:9000" # only reachable from the host itselfServices reach each other on the project network by service name and container port (db:5432). Publish a port only when something outside Docker needs it. Here db publishes nothing.
environment and env_file
environment sets variables in the container, like -e. It takes a mapping or a list:
environment:
DB_PASSWORD: workshop-pass
PORT: "5000"
environment:
- DB_PASSWORD=workshop-pass
- PORT=5000env_file loads variables from a file, like --env-file. One KEY=value per line; # starts a comment.
env_file:
- web.envWhen a variable is set in several places, the container gets one value:
| Priority | Source |
|---|---|
| 1 (wins) | environment: in compose.yaml |
| 2 | env_file: files |
| 3 | ENV in the image's Dockerfile |
Check what reached the container:
docker compose exec web envThe web service
services:
web:
build: .
ports:
- "8000:5000"
environment:
DB_PASSWORD: workshop-pass
env_file:
- web.env