10
5

LocalでDockerを用いてサーバー間の通信をするときは気をつけよう

Posted at

状況

フロントエンドはNext.js、バックエンドはRailsを用いて開発をしています。
Next.jsのサーバーコンポーネントでバックエンド側にリクエストをする際に、下記のようなエラーが発生しましたので、解決方法について説明したいと思います。

frontend_1  |  ⨯ unhandledRejection: TypeError: fetch failed
frontend_1  |     at Object.fetch (node:internal/deps/undici/undici:11372:11)
frontend_1  |     at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
frontend_1  |   cause: Error: connect ECONNREFUSED 127.0.0.1:8080
frontend_1  |       at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1555:16)
frontend_1  |       at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17) {
frontend_1  |     errno: -111,
frontend_1  |     code: 'ECONNREFUSED',
frontend_1  |     syscall: 'connect',
frontend_1  |     address: '127.0.0.1',
frontend_1  |     port: 8080
frontend_1  |   }
frontend_1  | }

解決策

今回のエラーはNext.js側でサーバーコンポーネントを使ったことに原因がありました。
この場合、二つのサーバーが通信することになりますが、
LocalでのDocker環境で同じローカルホストアドレスを使うと、自分自身にリクエストをかけることになるためエラーになります。
詳細はこちらをご参考ください。https://www.sambaiz.net/article/359/

解決策としては、fetchをする際のURLをhttp://localhost:8080/api/v1/users/1/urls/2からhttp://backend:8080/api/v1/users/1/urls/2に修正することです。
backendはDockerのサービス名になります。

docker-compose.yml
version: '3.8'
services:
  backend:
getUser.jsx
export default async function getUser() {
  const response = await fetch(`http://backend:8080/api/v1/users/1/urls/2`)
  if (!response.ok) {
    throw new Error('fail')
  }
  return await response.json()
}

余談

サーバーコンポーネントも単純にもう一つのサーバーであることで、思わぬ所からエラーになりますね。
何時間を調べても解決策がわからなkったのですが、Twitter(X)でエラーが発生して大変だと涙を流してたら、
いろんな方からアドバイスをいただき、解決できました。(ありがとうございます!)
https://x.com/wanchanmask/status/1736378307866919174?s=20

おそらくアドバイスがなかったら解決できなかったと思います。😭

それでは、読んでいただきありがとうございました!

10
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
5