Docker ComposeでDB起動後もアプリが接続拒否されるとき、healthcheckと依存条件を照合する

Docker ComposeのDB接続拒否を、接続先、runningとready、healthcheck、起動後の再接続から切り分けます。

AIものさし編集部

Docker ComposeでDBコンテナがrunningでも、アプリから接続できる準備が終わったとは限りません。ただし、接続拒否をすべて起動待ち不足と決めつけるのも早計です。アプリがどのhost・portへ接続しているかを確かめ、その後にDBのready状態と依存条件を確認します。

この記事は現在のDocker Composeでdocker compose upを使う構成の診断です。Swarmや古いdocker-compose、別の起動経路へ同じ待機動作を保証するものではありません。以下は架空のサービス構成で、DBやコンテナの起動・接続試験は行っていません。

接続拒否と認証失敗を分ける

まずアプリのエラー本文、発生時刻、接続先のhostとport、対象Compose projectを記録します。passwordを含む接続文字列の全文やCompose設定全体をログへ貼りません。接続拒否、名前解決、timeout、DB認証、schema不在は、それぞれ確認先が異なります。

表は横にスクロールできます

症状最初に確認する対象すぐには決めないこと
名前を解決できないservice名・network・projectDBの起動時間
接続拒否host/port・listener・ready状態passwordだけが原因
接続timeout経路・network・到達性healthcheck追加で必ず解決
DBの認証エラーuser・接続先・認証条件containerの起動順
接続後にtableがないmigration・初期化TCP待機だけで十分

エラーの表現はDBやdriverによって違います。コード名だけでなく、どの段階まで進んだかを読みます。失敗後にappだけを再起動すると通る場合も、起動待ちが原因の可能性を示すにとどまり、接続先やnetworkの確認を省略する証拠にはしません。

appから見たhostとcontainer portを確認する

Docker Composeのnetworking資料(新しいタブで開く)では、同じnetwork上のサービスはservice名で到達でき、サービス間通信はcontainer portを使います。hostへ公開したportとは役割が違います。

架空例でDB service名がdb、container側portが5432、host公開portが15432なら、同じCompose networkのappは通常db:5432を使う構成です。host上のツールがlocalhost:15432で接続できても、app containerの同じ文字列が正しいとは限りません。container内のlocalhostがどのnetwork namespaceを指すかを確認します。

表は横にスクロールできます

接続する場所架空の接続先確認する前提
同じnetworkのapp servicedb:5432service名と共通network
Docker hostの検証ツールlocalhost:15432port公開とbind先
別projectのapp構成に応じた名前とport共通networkなどの設計

固定container IPへ書き換えて一時的に通す方法を恒久修正にしません。再作成でIPが変わり得るため、service名と接続の再確立を前提にします。DBを外部公開することも、同networkの接続拒否に対する必須手順ではありません。

runningとreadyを依存条件で分ける

Composeのstartup order資料(新しいタブで開く)は、通常の起動でcontainerがrunningになるまで待っても、readyまでは待たないと説明しています。depends_onがあるだけで、DBがSQLを受け付けるまで待つとは読み替えません。

DBのhealthcheckと、app側の依存条件service_healthyを組み合わせる場合、何を健康と判定しているかが重要です。プロセスがあるだけなのか、接続を受けるのか、必要な初期化まで終わったのかで、appへ与える保証が違います。

表は横にスクロールできます

確認対象測っている状態測っていない可能性
container runningprocessが動いているDB接続受付
DB固有のready probeprobeが確認する受付状態app用userの権限
appと同等の最小接続その接続条件で応答するmigration完了・全query
migration完了定義したschema変更の終了後の切断への耐性

DB image内にprobeコマンドがあるか、認証の要否、interval・timeout・retries・開始猶予をDBの起動特性に合わせて決めます。secretをprobeのログへ出さず、失敗時に何が不健康だったかを判断できる形にします。固定秒数のsleepだけを「準備完了」の検査にはしません。

migrationと起動後の切断は別に扱う

DBが接続を受け付けても、アプリが必要とするschemaがあるとは限りません。migration用の一回限りのサービスを使う設計なら、正常完了を待つ条件service_completed_successfullyなど、目的に合う依存契約を公式仕様で確認します。healthcheckに重いmigrationを毎回実行させるのではなく、準備検査と状態変更を分けます。

また、起動時の待機は運用中のDB再起動に対する再接続の代わりにはなりません。接続が切れたらアプリ側が再解決・再接続できるか、再試行に上限があるか、処理途中のtransactionをどう扱うかを確認します。依存サービスの再起動連動設定があっても、すべての障害を自動回復する保証にはしません。

同じ条件で復旧を確認する

起動コマンド、Compose ファイル、profile、project、CLI版を固定し、DBログとappの接続ログを同じ時刻で照合します。upと一回限りのrunなど、違う経路の結果を同じ待機仕様として比較しません。

検証用環境では、初回起動、既存DBがある再起動、DB停止後の再接続を分けます。結果には実施した経路、health状態、appの最小読取、未確認のmigrationや復旧条件を残します。volumeの削除やDBの初期化を接続診断の近道にはせず、永続データを保ったまま確認する計画にします。

確認した公式資料