第37章:依存関係(起動順)をざっくり扱う⏳
この章は「DB→APIの順で起動したはずなのに、APIがコケる😵」みたいな “順番問題” を卒業する回だよ〜!🎓✨ ポイントはこれ👇
- コンテナが起動した ≠ 中のアプリが利用可能(準備完了) 🙅♂️
- だから「順番」だけじゃなくて「準備完了まで待つ」も必要になることがある⏱️
1) まず大事:起動順で起きる“あるある事故”🪤😇
典型パターン👇
db(PostgreSQL)が立ち上がる🐘- でも内部初期化中で、まだ接続受付できない😴
apiが先にDBへ接続しようとして失敗💥- 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_healthy:healthcheckが通ったら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を先に作って起動する🐘 dbに healthcheckが通るまで待つ(=準備完了待ち)✅(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)⏲️📝
depends_onだけの状態で一度upして、ログに失敗が出るか観察👀healthcheck + service_healthyを入れて、再度upして改善を確認✅up -d --wait --wait-timeout 60を試して「待ててる」体験をする⏳(Docker Documentation)
まとめ🎉
- 起動順は
depends_on🧱 - 準備完了待ちは
healthcheck+condition: service_healthy🩺✅(Docker Documentation) - スクリプト運用なら
up -d --waitが便利⏱️(Docker Documentation)
次の章(第38章)は、この辺を踏まえて「起動/停止/ログ/初期化」を コマンド一発化 して、開発の儀式を短くしていくよ〜!🎮🚀