World map

 

BM: Baca dalam Bahasa Melayu

World D4: Set Meals

Wait until healthy: depends_on

You will learn: to make one dish wait until another is really ready.

Checked with Docker Engine 29 on 31 Oct 2026

The problem

Tap each point on the timeline.

Morning rush. The API starts too early. It calls a database that is still waking up. Tap each moment.

Watch

  web:
    depends_on: [api]
  api:
    depends_on: [db]

First to start at the top. Put these in order. Use the arrows, or drag.

  • web
  • db
  • api

depends_on: Who waits for whom. With condition: service_healthy, a dish waits until the other passes its health check. sets the start order. A dish starts after the dishes it depends on. Put the start order right.

Watch

  api:
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:18-alpine
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
      interval: 2s
      retries: 10
db shows Healthy first. Only then do api and web start. Docker transcript: $ docker compose up -d [+] up 5/5 ✔ Network kedai-kancil_default Created 0.1s ✔ Volume kedai-kancil_db-data Created 0.0s ✔ Container kedai-kancil-db-1 Healthy 0.3s ✔ Container kedai-kancil-api-1 Started 0.3s ✔ Container kedai-kancil-web-1 Started 0.3s

Your laptop~/kedai-kancil

  • No open hatches

Lunchboxes (containers)

  • No containers yet

Frozen packs (images)

  • kedai-kancil-api:latest6 layers · 244MB
  • kedai-kancil-web:latest9 layers · 92.6MB
  • nginx:1.30-alpine8 layers · 93.5MB
  • node:24-alpine4 layers · 244MB
  • postgres:18-alpine9 layers · 433MB
  • redis:8-alpine7 layers · 162MB

0 containers (0 running), 6 images, 0 lockers.

Started is not ready. A health check is a taste test. pg_isready asks db: ready yet? service_healthy makes api wait for a yes.

Try it

Right now api waits only until db has started. Make it wait until db is healthy. Then order the set meal.

Build a set meal: add the services, then join their phone lines and lockers.

Menu (tap or drag)

Your set meal

  • web
    build: ./web
    Waits for
  • api
    build: ./api
    Waits for
  • db
    postgres:18-alpine
    Waits for

compose.yaml 27 lines

services:
web:
build: ./web
ports:
- "8080:80"
depends_on:
api:
condition: service_started
api:
build: ./api
environment:
DB_HOST: db
depends_on:
db:
condition: service_started
db:
image: postgres:18-alpine
environment:
POSTGRES_PASSWORD: example
volumes:
- db-data:/var/lib/postgresql
healthcheck:
test: ["CMD", "pg_isready", "-U", "postgres"]
interval: 2s
retries: 10
volumes:
db-data: {}

Predict

Someone deleted db’s password. Postgres exits at once. What does docker compose up -d do now?

Pick one answer.

Check

Run it and read the red line. Then ask db’s logs why.

Your laptop~/kedai-kancil

  • No open hatches

Lunchboxes (containers)

  • No containers yet

Frozen packs (images)

  • kedai-kancil-api:latest6 layers · 244MB
  • kedai-kancil-web:latest9 layers · 92.6MB
  • nginx:1.30-alpine8 layers · 93.5MB
  • node:24-alpine4 layers · 244MB
  • postgres:18-alpine9 layers · 433MB
  • redis:8-alpine7 layers · 162MB

0 containers (0 running), 6 images, 0 lockers.

Real words: dependency failed to start. Plain words: db stopped, so the dishes waiting for it never started.

You did it!

You can now make a dish wait until another is healthy.

Go deeper (optional)

Three conditions: service_started (the short list form), service_healthy, and service_completed_successfully for a one-off job, like making tables. Add restart: true and Compose also restarts api after it restarts db. docker compose up -d --wait returns only when every dish is running or healthy. CI uses it.

Real mission

  1. docker compose up -d
  2. docker compose ps
  3. docker compose up -d --wait

0 of 3 steps done · Your ticks are saved.