追記(2024/07/16)
本記事はフロントエンドのNext.jsをSSRで使用する場合に該当します。CSRの場合は問題がありませんでした。
前提知識
- Dockerを使って、フロントエンドとバックエンドを別々のコンテナで開発していた
- フロントエンドにはNext.js14(AppRouter)、バックエンドにはRails7を使用
問題
フロントエンドからバックエンドへのAPI呼び出しを行おうとしたが、うまく通信ができなかった。
フロントエンドのコードでは、バックエンドのAPIエンドポイントをhttp://localhost:3000/api/...
のように指定していた。
原因
Dockerコンテナ内ではlocalhost
が指すのはコンテナ自身であり、別のコンテナを指すことができない。そのため、フロントエンドのコンテナからlocalhost
を使ってバックエンドのコンテナにアクセスしようとしても、正しく通信ができなかった。
解決方法
Next.jsコンテナの設定
Dockerコンテナ間で通信を行う際には、host.docker.internal
を使用する。host.docker.internal
は、Dockerコンテナから見たホストマシンのIPアドレスを表す特殊なDNS名である。
フロントエンドのコードを以下のように修正する。
// 修正前
const apiEndpoint = 'http://localhost:3000/api/...';
// 修正後
const apiEndpoint = 'http://host.docker.internal:3000/api/...';
Railsコンテナの設定
Railsコンテナ側では、config/environments/development.rb
ファイルに以下の設定を追加する。
config.hosts << "host.docker.internal"
この設定により、RailsがDocker外部からのリクエストを受け付けるようになる。
これらの修正によって、Next.jsのコンテナからRailsのコンテナへの通信が正常に行えるようになる。
まとめ
- Dockerコンテナ間でAPI通信を行う際は、
localhost
ではなくhost.docker.internal
を使用する必要がある -
host.docker.internal
は、Dockerコンテナから見たホストマシンのIPアドレスを表す特殊なDNS名 - Next.jsコンテナではAPIエンドポイントの指定を
host.docker.internal
に変更し、Railsコンテナではconfig.hosts
にhost.docker.internal
を追加する - Dockerを使った開発では、コンテナ間の通信方法を正しく理解しておくことが重要