Skip to main content

第37章:依存関係(起動順)をざっくり扱う⏳

この章は「DB→APIの順で起動したはずなのに、APIがコケる😵」みたいな “順番問題” を卒業する回だよ〜!🎓✨ ポイントはこれ👇

  • コンテナが起動した中のアプリが利用可能(準備完了) 🙅‍♂️
  • だから「順番」だけじゃなくて「準備完了まで待つ」も必要になることがある⏱️

1) まず大事:起動順で起きる“あるある事故”🪤😇

典型パターン👇

  1. db(PostgreSQL)が立ち上がる🐘
  2. でも内部初期化中で、まだ接続受付できない😴
  3. api が先にDBへ接続しようとして失敗💥
  4. APIが終了 → そのまま落ちる / 再起動ループ🔁😵‍💫

Composeの depends_on“起動順”は面倒見てくれる けど、デフォルトでは “準備完了”までは待たない んだ。(Docker Documentation)


2) 解決は「3レイヤー」構えが最強💪😄

レイヤーA:とりあえず起動順を固定(最低限)🧱

  • depends_on を書くと、依存関係の順に作成・起動/停止 してくれる👍(Docker Documentation)
  • ただし「動いてる(running)」までで、「使える(ready)」は別問題🙃(Docker Documentation)

レイヤーB:準備完了まで待つ(ここが本命)🩺✅

Composeは depends_on長い書き方 で、依存の条件を指定できるよ👇(Docker Documentation)

  • service_started:起動したらOK(=短い書き方相当)
  • service_healthyhealthcheckが通ったらOK(=準備完了待ち)🟢
  • service_completed_successfully:一発処理が成功して終わったらOK(マイグレーション等)🏁(Docker Documentation)

レイヤーC:アプリ側も“接続リトライ”を持つ(現場力)🔁🧠

DBは起動時だけじゃなく、再起動・一瞬の切断もあり得る😅 なので 「最初の接続が失敗しても数回リトライする」 を入れておくと強い💪 (この教材では“最小でOK”の方針でいくよ!)


3) ハンズオン:DB待ち問題を「わざと」踏んで直す😈➡️😇

ここでは Todo API(api)+Postgres(db) を想定するよ🧩 (PostgreSQLは現行系として postgres:18 を例にするね🐘✨)(postgresql.org)


3-1. まずは「失敗する」構成(症状を観察👀)

depends_on が無い or healthcheck無しだと、タイミング次第でAPIが先にDBへ行ってコケることがある😵


3-2. 直す:healthcheck + service_healthy を入れる✅

以下は “最小で効く” 例だよ(超よく使う形)👇

services:
db:
image: postgres:18
environment:
POSTGRES_USER: todo
POSTGRES_PASSWORD: todo
POSTGRES_DB: todo
volumes:
- todo-db:/var/lib/postgresql/data
healthcheck:
# Postgres公式イメージに入ってる pg_isready を使うのが定番 👍
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 5s
timeout: 5s
retries: 10
start_period: 10s

api:
build: ./api
environment:
# 例:あなたのAPI側の読み方に合わせてね(DATABASE_URLでもOK)
DB_HOST: db
DB_PORT: "5432"
DB_USER: todo
DB_PASSWORD: todo
DB_NAME: todo
depends_on:
db:
condition: service_healthy
restart: true

volumes:
todo-db:

ここで起きること👇

  • Composeは db を先に作って起動する🐘
  • dbhealthcheckが通るまで待つ(=準備完了待ち)✅(Docker Documentation)
  • その後で api を起動する🚀
  • さらに restart: true を付けると、docker compose restart db みたいに Compose操作でdbを再起動した時にapiも再起動 されやすくなる(再接続しやすくなる)🔁(Docker Documentation)

🧠豆知識:$${POSTGRES_USER} みたいに $ を2個にしてるのは、Composeの変数展開と衝突しないための“エスケープ”だよ😺(ここ、初心者がハマりやすい!)


3-3. 動かして確認するコマンド🧪

docker compose up --build

ログを見て「dbがhealthyになってからapiが起動」っぽい流れになってればOK👍

別ターミナルで👇

docker compose ps
docker compose logs -f db
docker compose logs -f api

片付け👇(DBデータも消すなら -v)🧹

docker compose down -v

4) “待てるCompose”にする小ワザ:up --wait ⏱️✨

スクリプトやCIで「起動したら次の処理へ進みたい」時に便利なのがこれ👇

docker compose up -d --wait --wait-timeout 60
  • --wait:サービスが running/healthy になるまで待つ(detach扱いになる)(Docker Documentation)
  • --wait-timeout:待ち時間に上限を付ける(ハング防止)(Docker Documentation)

✅ healthcheckが無いと「healthy」判定できないので、結局 healthcheck 設計が大事だよ〜!


5) よくある罠まとめ(ここだけ読んでも強くなる🛡️😄)

  • depends_on だけだと “ready待ち”はできない(デフォルトは「動いたらOK」)😇(Docker Documentation)

  • service_healthy を使うなら healthcheck必須 ✅(Docker Documentation)

  • restart: true(depends_on内)と、サービス直下の restart: always は別物だよ⚠️

    • 前者:Compose操作に連動して依存側を再起動しやすくする🧩(Docker Documentation)
  • もし condition を書いたら怒られる(YAMLが無効って言われる)場合、古い docker-compose を踏んでる可能性がある😵

    • docker compose version で確認して、できれば docker compose(V2)に寄せよう👍

6) AI活用(コピペで使えるプロンプト集🤖✨)

  • 「この compose.yml の db に、Postgres向けのhealthcheck を入れて。depends_on: service_healthy で api を待たせたい。初心者向けに短く説明もつけて」
  • 「Node/TypeScript で、DB接続を 最大10回リトライ(指数バックオフ)する最小コードを書いて。ログも分かりやすく」
  • 「“起動した≠準備完了” を、文系大学生向けの例え話で3つ作って😂」

7) ミニ演習(3分でOK)⏲️📝

  1. depends_on だけの状態で一度 up して、ログに失敗が出るか観察👀
  2. healthcheck + service_healthy を入れて、再度 up して改善を確認✅
  3. up -d --wait --wait-timeout 60 を試して「待ててる」体験をする⏳(Docker Documentation)

まとめ🎉

  • 起動順depends_on 🧱
  • 準備完了待ちhealthcheck + condition: service_healthy 🩺✅(Docker Documentation)
  • スクリプト運用なら up -d --wait が便利⏱️(Docker Documentation)

次の章(第38章)は、この辺を踏まえて「起動/停止/ログ/初期化」を コマンド一発化 して、開発の儀式を短くしていくよ〜!🎮🚀