[Docker] ネットワーク共有なしで、ホストポートを使用してコンテナ間通信する方法 (host.docker.internal)
タグ: Docker, DevOps, Network, host.docker.internal
1. 問題の状況
開発環境で複数のサービスをDockerで管理することがよくあります。
-
App-A(例: DRF)はnetwork-Aにあります。 -
App-B(例: Nextcloud)はnetwork-Bにあります。 -
2つのコンテナは同じホストマシンで実行されています。
-
App-Bはホストの8080ポートとバインディングされています。 (例:docker run -p 8080:80 ...)
App-AからApp-BをAPIで呼び出す必要があります。ただし、面倒なので2つのネットワークをブリッジで接続したくありません。ホストの8080ポートに直接アクセスできないのでしょうか?
コンテナ内からlocalhost:8080または127.0.0.1:8080を呼び出すと、これはホストマシンではなく、コンテナ自身を指します。
2. 解決策: host.docker.internal
最も簡単な解決策は、host.docker.internalという特別なDNS名を使用することです。
host.docker.internal: コンテナ内からホストマシンのIPアドレスに解釈される特別なホスト名です。
App-A (DRF)のコードからNextcloudを呼び出す際、URLを次のように設定します。
# DRF (App-A) 内部コード
import requests
# 'localhost'の代わりに'host.docker.internal'を使用します。
NEXTCLOUD_URL = "http://host.docker.internal:8080"
try:
response = requests.get(NEXTCLOUD_URL)
print(f"Nextcloud接続成功: {response.status_code}")
except requests.exceptions.ConnectionError:
print("Nextcloud接続失敗")
コンテナ内でcurlを使ってテストする際も同様です。
# App-Aコンテナ内で実行
curl http://host.docker.internal:8080
3. ⚠️ 注意: Linuxホスト環境設定
Docker Desktop (macOS, Windows)を使用している場合、host.docker.internalはデフォルトで機能します。
しかし、Linuxホスト環境では、この設定を手動で追加する必要があります。host-gatewayという特別なキーワードを使用して、ホストIPをマッピングできます。
方法1: docker runを使用する場合
--add-hostフラグを追加します。
docker run \
--add-host=host.docker.internal:host-gateway \
--network network-A \
my-drf-app-image
方法2: docker-compose.ymlを使用する場合
App-A (DRF)サービスにextra_hostsを追加します。
services:
drf-app:
image: my-drf-app-image
networks:
- network-A
extra_hosts:
# host.docker.internalをホストマシンのIP(host-gateway)にマッピング
- "host.docker.internal:host-gateway"
# ... (network-Aの定義) ...
4. まとめ
分離されたDockerネットワーク間で通信を行う場合、ネットワークを複雑に接続する必要はありません。
-
呼び出し対象のコンテナ(Nextcloud)をホストポート(
8080)にバインドします。 -
呼び出すコンテナ(DRF)から
http://host.docker.internal:8080アドレスにリクエストを送ります。 -
ホストがLinuxの場合、呼び出すコンテナに
extra_hosts(host.docker.internal:host-gateway)設定を追加することを忘れないでください。
コメントはありません。