メインコンテンツまでスキップ

第28章:Composeの起動順:healthyになってから次へ ⏳🔁

① 今日のゴール 🎯✨

この章が終わると、次ができるようになります👇😊

  • 「DBが起動した “だけ” じゃダメで、使える状態(healthy) になってからAPIを起動」できる ✅
  • Composeの depends_on条件付き(condition) で書ける ✅(service_started / service_healthy / service_completed_successfully)(Docker Documentation)
  • healthcheck をCompose側で設定して、起動直後の“接続失敗ログ”を減らす ✅(Docker Documentation)
  • スクリプト/CIで便利な docker compose up -d --wait も使える ✅(Docker Documentation)

② 図(1枚)🖼️🧠

DBは「起動中…」の時間があるので、そこを待つのがポイントです👇

[dbコンテナ]  起動 ▶ healthcheck合格(healthy) ▶ OK🙆

└──(ここを待てたら勝ち🥳)

[apiコンテナ] 起動 ▶ /ready が最初から通りやすい✨

Composeは基本、依存順に“起動はする”けど、“ready(利用可能)”までは待たないんでした。(Docker Documentation) そこで healthcheck + condition: service_healthy を使います 💪😼(Docker Documentation)


③ 手を動かす(5〜10手順)🛠️🚀

ここでは「DB(Postgres) → API(Node/TS)」のよくある構成でやります😊 (ファイル名は compose.yaml でも docker-compose.yml でもOKです)


Step 0️⃣:フォルダ構成(例)📁

project/
compose.yaml
api/
Dockerfile
package.json
src/
index.ts

Step 1️⃣:まず“ダメな起動順”を体験する 😇💥

compose.yaml(ダメ版):depends_on はあるけど「healthy待ち」じゃない

services:
db:
image: postgres:18
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: app
POSTGRES_DB: app

api:
build: ./api
environment:
DATABASE_URL: postgres://app:app@db:5432/app
depends_on:
- db
ports:
- "3000:3000"

これで起動👇

docker compose up --build

起動直後、APIがDBに接続しようとして 「接続できない!」ログ が出ることがあります😵‍💫 (Composeは“コンテナが起動して動いてる”ところまでで、DBが接続受付できるかは待たないため)(Docker Documentation)


Step 2️⃣:DBに healthcheck を付ける 💚🩺

次はDB側に healthcheck を付けます。Composeの healthcheck は DockerfileのHEALTHCHECKと同様の仕組みで、Compose側で値を上書きもできます。(Docker Documentation)

compose.yaml(改善①:dbにhealthcheck追加)

services:
db:
image: postgres:18
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: app
POSTGRES_DB: app
healthcheck:
# Postgres公式イメージに入ってる pg_isready を使う定番パターン👍
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB} -h localhost"]
interval: 5s
timeout: 3s
retries: 20
start_period: 10s
# start_interval は Docker Compose v2.20.2 で導入(起動直後のチェック間隔を短くしたい時に便利):contentReference[oaicite:7]{index=7}
start_interval: 2s

api:
build: ./api
environment:
DATABASE_URL: postgres://app:app@db:5432/app
depends_on:
- db
ports:
- "3000:3000"

💡ポイント:$${POSTGRES_USER} みたいに $ を2個にしてるのは、Composeの変数展開とぶつからないようにするためです(これ、超つまづきポイント😇🪤)


Step 3️⃣:depends_on を“条件付き”にする ⏳✅

ここが本命です🔥 depends_onlong syntax を使って、condition: service_healthy を指定します。(Docker Documentation)

compose.yaml(改善②:healthyになるまでAPIを待つ)

services:
db:
image: postgres:18
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: app
POSTGRES_DB: app
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB} -h localhost"]
interval: 5s
timeout: 3s
retries: 20
start_period: 10s
start_interval: 2s

api:
build: ./api
environment:
DATABASE_URL: postgres://app:app@db:5432/app
depends_on:
db:
condition: service_healthy
# restart: true は「Compose操作による依存サービスの更新時に、依存先が更新されたらこのサービスも再起動」:contentReference[oaicite:9]{index=9}
restart: true
ports:
- "3000:3000"

✅これで、Composeは dbがhealthyになるまで apiを開始しない という挙動になります。(Docker Documentation)


Step 4️⃣:動作確認コマンド 👀🧾

起動👇

docker compose up --build

別ターミナルで状態確認👇

docker compose ps

見たいポイントはここ👇😆

  • db の STATUS に healthy が付く(時間差で付く)
  • その後に api が起動してくる(“接続失敗ログ”が減る)✨

Step 5️⃣:スクリプト/CIでさらに便利にする(おまけ)🤖🏗️

docker compose up -d --wait は、サービスが running / healthy になるまで待ってから コマンドが返ります(しかも detached を暗黙で使います)。(Docker Documentation)

docker compose up -d --wait --wait-timeout 120

⚠️注意:docker compose wait は “起動待ち” じゃなくて、コンテナが停止するまで待つコマンドです。名前が紛らわしい〜🤣🪤(Docker Documentation)


④ つまづきポイント(3つ)🪤😵‍💫

  1. depends_on だけで“ready待ち”できると思っちゃう → 起動順にはなるけど、ready(利用可能)は待たないのが基本です。(Docker Documentation) → 対策:condition: service_healthy を使う ✅(Docker Documentation)

  2. healthcheck が失敗し続けて “unhealthy沼” 😇 → start_period を増やす / retries を増やす / timeout を伸ばす、が効きます。healthcheck の各項目はComposeの正式オプションです。(Docker Documentation)

  3. $${POSTGRES_USER}$POSTGRES_USER にして死ぬ 💀 → Composeの変数展開と混ざって、意図通りに実行されないことがあります。 → 対策:コンテナ内の環境変数を参照したいときは $ をエスケープする癖をつける 🙆‍♂️


⑤ ミニ課題(15分)⏳🎮

課題A(やさしめ):わざとDBの起動を遅くして、待ててるか観察👀

  • start_period を 1s にしてみる(失敗しがち)→ 20s に戻す(成功しやすい)
  • docker compose ps の STATUS がどう変わるかメモ📝

課題B(ちょい実戦):initコンテナ(DBマイグレーション)を挟む🧪 service_completed_successfully を使って「マイグレーション完了後にAPI起動」にしてみよう✨(Docker Documentation)

(例イメージ)

depends_on:
migrate:
condition: service_completed_successfully

⑥ AIに投げるプロンプト例(コピペOK)🤖📋✨

プロンプト1:healthcheck をいい感じに作る

Docker Compose の db(Postgres) に healthcheck を付けたい。
pg_isready を使って、起動が遅い環境でも安定する interval/timeout/retries/start_period のおすすめ値を提案して。
compose.yaml の該当部分だけ YAML で出して。

プロンプト2:depends_on の設計をチェックしてもらう

この compose.yaml の depends_on 設計は妥当?
「起動直後の接続失敗ログを減らしたい」という目的に対して改善案があれば教えて。
(condition の種類も含めて)

次の章(第29章)は、ログ🧾→メトリクス📈→ヘルス💚 を “一本の型” にまとめて、障害対応の手順をテンプレ化していきますよ〜🔥🕵️‍♂️🧯