Configuration through the environment
Why pass DATABASE_URL as an environment variable instead of hardcoding it in the code? Because the same image from lesson 3-1 must run everywhere: your laptop, the CI server (CI is short for continuous integration: an automated machine that tests every push, and unit 7 is devoted to it), and production. The code stays identical, only the environment changes per machine. This is such a strong convention it has a name, the twelve-factor config rule.
The database side of the pair needs its own env vars. The official postgres image reads these on first boot:
db:
image: postgres:16
environment:
POSTGRES_USER: shop
POSTGRES_PASSWORD: secret
POSTGRES_DB: shop
volumes:
- dbdata:/var/lib/postgresql/dataUser, password, and database name here must match what the app's DATABASE_URL claims, or connections fail. When you hit a broken compose stack, comparing these two blocks is the first debugging move.
Code exercise · bash
Your turn: connection URLs are assembled from exactly the pieces in the env blocks. Using the five variables, print the DATABASE_URL the app needs, in the form postgres://user:password@host:port/dbname
What depends_on does and does not do
depends_on:
- dbThis controls start order only: compose launches db before app. It does not wait for Postgres to actually be ready to accept connections, which takes a few seconds after the container starts.
So the app can still boot, try to connect, and fail while the database is warming up. Two real fixes:
- The app retries its database connection on startup (good practice regardless)
- A healthcheck on the db service, plus
depends_onwithcondition: service_healthy, so compose waits for genuine readiness
Healthchecks get their own treatment in lesson 9-2. For now, remember the trap: started is not ready.
Quiz
With plain `depends_on: [db]`, compose starts db first, yet the app still crashes with "connection refused" on a slow machine. Why?
Problem
In the db service block, POSTGRES_PASSWORD is set to secret, but the app's DATABASE_URL says postgres://shop:hunter2@db:5432/shop. What happens when the app tries to connect: success or failure?