localhostではなく、host.docker.internalでアクセスする
最近、ローカルPC上でdocker composeを使用して、Next.jsで構築したフロントエンドとGolangで構築したバックエンドAPIを、それぞれ独立したDockerコンテナで開発していました。
ここで、フロントエンドからバックエンドのAPI実行時に、localhostを使用してもうまく接続できないという問題に直面しました。
調査の結果、コンテナ内のlocalhostはコンテナ自身を指すため、他のコンテナやホストマシン上のサービスにアクセスできないことが原因だと判明しました。そこで出会ったのがhost.docker.internalです。
コンテナ内のlocalhostがコンテナ自身を指すため、他のコンテナやホストマシン上のサービスにアクセスできないという問題があります。
そんな時に便利なのがhost.docker.internalです。
localhostがコンテナ内部を指す問題
コンテナ内でlocalhostを使用すると、それはコンテナ自身を指します。
つまり、コンテナ内で http://localhost:8080 にアクセスしても、ホストマシン上で実行されているサービスには到達できません。
これは、各コンテナが独立したネットワーク環境を持っているためです。
例えば、バックエンドのコンテナAPIサーバーがlocalhost:8080で実行されていて、フロントエンドのコンテナからそのAPIサーバーにアクセスしようとしても、http://localhost:8080 では接続できないことがあります。
コンテナ内のlocalhostはコンテナ自身を指すため、コンテナ内部に存在しないサービスへアクセスしようとしていることになります。
host.docker.internalの役割
host.docker.internalは、この問題を解決するための特殊なDNS名です。
コンテナ内でhost.docker.internalを使用すると、ホストマシン上で実行されているサービスにアクセスすることができます。
つまり、先ほどの例で、コンテナ内のフロントエンドからAPIサーバーにアクセスする場合、http://localhost:8080 の代わりに http://host.docker.internal:8080 を使用することで、ホストマシン上のAPIサーバーに到達できます。
使用方法
コンテナ内からホストマシン上のサービスへアクセスする際に、localhostの代わりにhost.docker.internalを使用します。
添付画像では、NEXT_PUBLIC_API_URL=http://localhost:8080
とNEXT_PUBLIC_API_URL=http://host.docker.internal:8080
の二つが存在します。
今回、NEXT_PUBLIC_API_URL=http://host.docker.internal:8080
の設定をすることで、事象が解消しました。
エラー: NEXT_PUBLIC_API_URL=http://localhost:8080
成功: NEXT_PUBLIC_API_URL=http://host.docker.internal:8080
まとめ
コンテナ内のlocalhostがコンテナ自身を指すことによって、他のコンテナやホストマシン上のサービスにアクセスできないという問題があります。
host.docker.internalを使用することで、この問題を解決し、コンテナ内からホストマシン上で実行されているサービスにアクセスすることができます。
ぜひ、host.docker.internalを活用して、コンテナとホストマシン間のシームレスな連携を実現してください。