docker上でnextを使用したフロントエンドを開発しているときにgetdata()をするとfetch failedというエラーが発生する問題に直面しました。
TypeError: fetch failed
at Object.fetch (/frontend/node_modules/next/dist/compiled/undici/index.js:1:26669)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
cause: Error: connect ECONNREFUSED 127.0.0.1:8080
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1247:16)
at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 8080
}
}
以下のページでは、「localhostではなく、127.0.0.1を指定する」という解決法がありましたが、これを試しても解決しませんでした。
悪戦苦闘しつつも、なんとか解決できたので共有させていただきます。
結論
例えば、以下のようなコードの場合、「localhost:8080」をコンテナのIPに置き換えると解決できます。
async function getData() {
try {
const res = await fetch('http://localhost:8080/posts', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
}
});
コンテナのIPは以下の方法で確認できます。
まず、以下のコマンドでコンテナIDを確認します。
docker ps
次に、以下のコマンドを「コンテナID」を先ほど確認したコンテナIDに置き換えた上で実行します。
docker inspect コンテナID | grep IPAddress
すると、"IPAddress"としてコンテナのIPが表示されます。
コンテナのIPを固定する
コンテナのIPはコンテナを起動し直すたびに変更されてしまうため不都合です。そこで、docker-compose.ymlでコンテナのIPを固定することで不都合を解決することができます。
version: "3.3"
services:
frontend:
...
networks:
fixed_compose_network:
ipv4_address: 10.254.249.89
...
networks:
fixed_compose_network:
ipam:
driver: default
config:
- subnet: 10.254.249.0/24
こうすることで、毎回IPアドレスを書き換える必要がなくなります。
最後に
本番環境で独自ドメインにfetchをする際には、当該ドメインを指定すれば問題なく動作しました。ローカルで開発するときだけ、少し変則的な対応が必要なようです。
参考資料