network_mode: service:vpn と消えた db ホスト名
VPN の名前空間を共有するかどうかはトポロジーの選択です。db が自分のアドレスを保ち vpn がそのネットワークに参加するか、すべてが loopback で応答するかのどちらかです。
network_mode: service:vpn をアプリに追加してスタックを再起動すると、db が解決されなくなりアプリが落ちます。compose ファイルでは何も名前を変えていないので、疑わしいのは DNS とデータベースです。実際の変化はもっと小さく奇妙で、アプリがその名前の存在する Compose ネットワークのメンバーでなくなったのです。データベースがどの名前空間から応答すべきかを決めるまで、ホスト名の修正はすべて推測になります。
db ホスト名が解決されなくなった理由
network_mode を使うサービスは Compose ネットワーク上に自分のアドレスを持たず、指定したサービスの名前空間を借ります。その名前空間は独自のインターフェース、ルート、ポート空間、リゾルバを持ち込み、アプリの backend ネットワークへの接続を置き換えます。db という名前は決して抽象的なものではなく、そのネットワーク上に存在し、組み込みの DNS で解決されていました。接続を外せば、その名前を解決する場所はなくなります。
確認はホストからではなくコンテナの内部で行います。アプリでは失敗しデータベースのコンテナでは成功するなら、名前は正しく、メンバーシップが間違っているということです。その結果は修正箇所をアプリのリゾルバ設定ではなく compose のトポロジーに置きます。
ファイルを編集する前の三つの問い
どれもトポロジーを狭めるので、順番に答えてください。データベースは何に対して応答すべきか、他のコンテナが使うホスト名か、それとも loopback 上のアプリだけか。アプリはホストにポートを公開すべきか、公開するならどのサービスが持ち主になるか。データベースはホストや別のマシンから到達可能であるべきか、それともトンネルの内側からだけか。
データベースに自分の名前が必要でアプリが何も公開しないなら、別々の接続に置きます。アプリがポートを公開する必要があり、すべてがトンネルを通るなら、データベースを VPN の名前空間に入れて loopback を使います。両者を混ぜると、きれいに起動して接続時に失敗するスタックになります。
データベースはそのままの場所に置く
小さな変更は、名前空間の持ち主をデータベースが既にあるネットワークに接続します。アプリは vpn スタックを共有しているのでその接続を引き継ぎ、db は以前とまったく同じに解決されます。
services:
vpn:
networks:
- backend
app:
network_mode: service:vpn
db:
networks:
- backend
networks:
backend:networks もアプリに追加しないでください。Compose は同じサービス内で network_mode と併用されるこのプロパティを拒否し、エラーはその組み合わせではなくファイルを指します。VPN クライアントが名前空間の内側で backend の宛先をフィルタする場合は、共有接続が経路を提供してもそのフィルタは打ち消されないため、サポート対象のローカルネットワークポリシーも調整してください。
データベースを名前空間に移す
大きな変更はデータベースを同じ名前空間に置き、アプリを実際のポートで 127.0.0.1 に向けます。別々のコンテナで起動したというだけで二つのプロセスが同じアドレスとポートを同時にバインドすることはできないので、wildcard アドレスでも待ち受けるデータベースは同様にする他の何かと衝突します。移す前にリスナーを確認してください。
公開ポートは名前空間を持つサービスに属します。アプリに ports を追加することは network_mode と併用で拒否され、別のアプリ用アドレスをでっち上げるのは存在しないインターフェースを記述することになります。
準備状態、ブロック、リゾルバ
depends_on はコンテナの起動順を決めるだけで、トンネルが上がっている証拠ではなく、トンネルが切れたときに通信を止めもしません。到達性、トンネルの準備状態、障害時のブロックを三つの別々の要件として扱ってください。最初の一つだけを満たすスタックは、良い日には手動テストに通り、悪い日には漏れます。三つの答えは compose ファイルのそばに書いておき、次の人が見る場所にしてください。
名前空間を共有すると、アプリが VPN コンテナのリゾルバを引き継ぐことになり、トンネルが DNS サーバーを押し付けるときは助けになり、そうでないときは混乱を招きます。ホストのリゾルバが当てはまると仮定せず、名前空間に実際に何が入っているかを確認してください。Compose のサービスリファレンス は network_mode、ports、依存関係の挙動を一か所にまとめており、network_mode のサービスが独自のアドレスを持たない理由も説明しています。