コンテナからホストを参照する - host.docker.internal
コンテナから「ホスト側の localhost」に繋ぎたいときに使う特殊名。Docker Desktop では最初から解決できるが、Linux では `--add-host=host.docker.internal:host-gateway` を付ける必要がある。
概念図
構文
docker run --add-host=host.docker.internal:host-gateway <image>実例
コンテナからホストの 5432 ポートにアクセス
# Docker Desktop: そのまま動く / works out of the box
docker run --rm curlimages/curl \
curl -v http://host.docker.internal:5432
# Linux: host-gateway の明示が必要 / must add host-gateway on Linux
docker run --rm \
--add-host=host.docker.internal:host-gateway \
curlimages/curl curl -v http://host.docker.internal:5432compose.yml で host-gateway を OS 横断で設定する
services:
api:
image: myorg/api
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
DATABASE_URL: postgres://host.docker.internal:5432/appDocker Desktop では使える
Docker Desktop(macOS / Windows)では、host.docker.internal という特殊な DNS 名が最初から有効になっており、コンテナ内部から参照すると「ホスト OS 側」に解決される。
たとえば macOS の開発 PC で直接起動している Postgres(localhost:5432)に、コンテナの中から host.docker.internal:5432 で接続できる。
これは Desktop が裏で走らせている軽量 VM が、VM ↔ ホスト間の特別なブリッジを用意しているために成立している仕組み。
IDE や開発ツールをホスト側で動かしつつ、一部のサービスだけコンテナ化する構成でよく使われる。
Linux では `--add-host=host.docker.internal:host-gateway`
Linux の素の Docker Engine には host.docker.internal の事前設定が無く、何もしないと名前解決に失敗する。
解決には docker run 時に --add-host=host.docker.internal:host-gateway を指定する。
host-gateway は Docker 20.10 以降で追加された特別な識別子で、コンテナから見たホストの IP(通常は Docker ブリッジのゲートウェイ)に自動で置き換えられる。
Compose の場合は各サービスに extra_hosts: ["host.docker.internal:host-gateway"] を書いておけば OS を問わず同じ挙動になる。
この一行をテンプレに入れておくと、Docker Desktop 前提で書かれた設定が Linux CI でも動くようになる。
docker run --rm \
--add-host=host.docker.internal:host-gateway \
alpine sh -c "getent hosts host.docker.internal"なぜこの差があるのか
Docker Desktop は macOS や Windows の上で Linux コンテナを動かすために、裏側で常に軽量 Linux VM を動かしている。
この VM とホスト OS を繋ぐ特別なネットワーク経路が必要で、その終端に分かりやすい名前として host.docker.internal が予約されてきた経緯がある。
一方、Linux ネイティブ環境ではコンテナとホストが同じカーネルで動くため、ブリッジのゲートウェイ IP さえ分かれば通信自体はできるが、その IP はネットワーク構成で変わる。
そこで「動的に解決してくれるエイリアス」が必要となり、host-gateway による --add-host という明示オプションが後付けで整備された。
結果として、同じ名前でも「標準装備」の Desktop と「手で有効化」の Linux という差が残っている。
関連トピック
bridge / host / overlay- Docker のネットワークドライバは bridge・host・overlay などに分かれ、用途が違う。user-defined bridge では DNS 解決が働き、`--network host` は Linux と Docker Desktop で挙動が大きく異なる。 volume / bind mount- volume は Docker が管理する永続領域、bind mount はホストの任意パスをそのまま見せる機能。UID/GID ズレや SELinux ラベルが原因で「書き込めない」エラーが起きがちなので、対処パターンを押さえる。 