はじめに
今回はDocker環境でAPI通信にうまくいかなくプチハマりした事と、
その解決方法について共有したいと思います。
開発環境
Ruby on Rails(API側)
Next.js(クライアント側)
Postgres(データベース)
Docker/Docker-compose
本文
APIサーバー(Rails)からクライアントに表示させるときは、
今回の場合API通信がrailsとPostgresからのNextなのでDockerのネットワーキング内に収まります、
なのでこのようにサービス名で大丈夫なのでこのコードでいいのですが
await axios.get("http://サービス名:ポート番号/エンドポイント"
クライアントサーバー(ブラウザでフォーム通信よってコンテナ外)からrailsにAPIを叩くと。。。
"Failed to load resource: net::ERR_NAME_NOT_RESOLVED"
というエラーメッセージに遭遇しました。
このエラーの原因は、サーバー名が見つからないためでした。
Dockerコンテナ外部からdockerにアクセスするためには、
dockerのホストIPアドレスを教えてあげる必要がありました!
つまり、クライアントサーバー(ブラウザでフォーム通信など)からrailsに叩くときは、
DockerホストのIPアドレスと公開されている(exposeされた)ポート番号を使用する必要があります。
たとえAPIサーバー(rails)とクライアント(Next.js)の両方が
Docker上で動作している場合でも、この方法が必要になります。
await axios.post("http://dockerホストのIPアドレス:ポート番号/エンドポイント"
まとめ
Dockerコンテナ内から他のDockerコンテナに通信する場合(この場合、RailsからPostgresへの通信など)、Docker内部のネットワーキングが利用できます。
しかし、Dockerコンテナ外部から(つまり、ブラウザなどのクライアントから)Dockerコンテナ内部のサービスに通信する場合、DockerホストのIPアドレスと公開されている(exposeされた)ポート番号を使用する必要があります。
因みにターミナルにこのコマンドを打つとdockerのホストIPが確認できます。
ifconfig
余談
開発環境をすべてローカルで構築している場合、(Dockerでない場合)
APIを叩くためにはlocalhost:3000/エンドポイントのように指定するだけでいいみたいです。
最後に
APIを作成したらPostmanのようなAPIテストツールを使いちゃんとレスポンスが返ってくるのかを
確認する癖をつけたいと思いました!
そして返ってきたらAPI(Rails)が悪いのではなく指定の仕方が悪いと原因が特定しやすいです。
これまでの学習では、Railsだけで開発を進めてきましたが、
クライアントとサーバーを分けて学習するのは今回が初なので苦戦してしまいました
もっといい方法があるかもしれませんが今回はこのような形で無事解決しました。
API操作は使用頻度はかなり多いと思いますし、
同じミスで時間を潰したくないので積極的にアウトプットしていきます!
お疲れ様でした!