Node.jsの「getaddrinfo ENOTFOUND」エラーを解決する:実践ガイド

intermediate🌐 Networking2026-05-25| Node.js (v14+), Linux (Ubuntu/Debian), macOS, Dockerコンテナ

Error Message

Error: getaddrinfo ENOTFOUND api.example.com
#nodejs#dns#ネットワーク#getaddrinfo#docker

アプリがターゲットを見つけられないときNode.jsアプリケーションが完璧に動作している最中に、突然壁にぶつかることがあります。ログが次のような、コンピューター用語が入り混じったネットワークエラーで埋め尽くされます。

Error: getaddrinfo ENOTFOUND api.example.com
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:107:26)

平易な言葉で言えば、getaddrinfo ENOTFOUNDは、Node.jsがオペレーティングシステムにIPアドレスを尋ねた際、OSが「それが何なのか全く分かりません」と答えたことを意味します。これは404のようなサーバーエラーではありません。1バイトのデータが送信される前段階で発生する、「あなたはどこにいますか?」という問題です。

なぜこれが起こるのか?DNS解決はインターネットの電話帳のようなものです。このエラーは、ネットワークレイヤーでのルックアップに失敗したときに発生します。Node.jsはlibuvを介してスレッドプールを使用してこれらのシステムコールを処理するため、ここでの失敗は通常、JavaScriptロジックのバグではなく、環境の問題を指し示しています。

デバッグプロセス:根本原因の特定リファクタリングを始める前に、どこで障害が発生しているのかを切り分ける必要があります。コードなのか、コンテナなのか、それともネットワーク自体なのでしょうか?

1. 「プラグは刺さっていますか?」テストから始める誰もが経験することですが、45分間画面を凝視した挙句、.envファイルのタイポに気づくことがあります。すぐにホスト名を確認してください。私は以前、設定がexample.comではなくapi.exampel.comになっていたために、本番環境のクラッシュを2時間追いかけたことがあります。ターミナルから5秒間のクイックテストを実行しましょう。

ping api.example.com
# または
nslookup api.example.com

もしこれらのコマンドが「Host not found」や「NXDOMAIN」を返すなら、問題はNode.jsではありません。マシンのDNS設定、あるいはプロバイダー(ISP)に原因がある可能性が高いです。

2. 環境変数を監査する現代のアプリはprocess.envに大きく依存しています。dotenvを使用している場合は、ネットワークコールの前にロードされていることを確認してください。よくある落とし穴は、環境変数がまだロードされていないために、undefinedとなっているURLをフェッチしようとすることです。これにより、Node.jsは「undefined」という文字列そのものを解決しようとし、当然失敗します。

// 簡易的な健全性チェックを追加
if (!process.env.API_HOST) {
  throw new Error("致命的エラー: API_HOST 環境変数が欠落しています!");
}
console.log("接続先:", process.env.API_HOST);

3. Dockerの謎を解くDockerコンテナ内では、localhostは自分のコンピューターではなく、コンテナ自体を指します。APIが別のコンテナにある場合は、docker-compose.ymlで定義したサービス名を使用してください。たとえば、データベースサービス名がdb-serverであれば、接続文字列にはIPアドレス(スタックを再起動するたびに変わる可能性があります)ではなく、db-serverを使用すべきです。

実践的な解決策### プロトコルとホスト名を分離するhttp.requestのような低レベルのNode.jsモジュールは厳格です。これらはhostnamepathが分離されていることを期待します。もし誤ってhostnameフィールドにhttps://api.example.comを渡してしまうと、OSは文字通り「https://...」という名前のサーバーを探そうとし、ENOTFOUNDで失敗します。

const http = require('http');

const options = {
  hostname: 'api.example.com', // ホスト名のみ(プロトコルなし)
  port: 80,
  path: '/v1/users',
  method: 'GET'
};

const req = http.request(options, (res) => {
  console.log(`ステータス: ${res.statusCode}`);
});

req.on('error', (e) => {
  console.error(`ネットワーク障害: ${e.message}`);
});

req.end();

企業プロキシを通過する多くのオフィスでは、SquidやBlue Coatのようなプロキシを経由しないと外部の世界にアクセスできません。Node.jsはこれらを常に自動検出するとは限りません。内部ゲートウェイ(例:10.0.0.1:8080)を通じて正しくトラフィックをルーティングするために、https-proxy-agentのようなパッケージが必要になる場合があります。

const { HttpsProxyAgent } = require('https-proxy-agent');
const axios = require('axios');

const agent = new HttpsProxyAgent('http://10.0.0.1:8080');
axios.get('https://api.external.com', { httpsAgent: agent })
  .then(res => console.log("成功!"))
  .catch(err => console.error("プロキシエラー:", err.message));

検証ステップ修正を適用したら、それが確実に機能しているか体系的に検証しましょう。

  • DNSキャッシュをクリアする: macOSではsudo killall -HUP mDNSResponderを実行します。Windowsではipconfig /flushdnsを使用します。これにより、古い壊れたレコードを参照していないことを確認できます。- cURLでテストする: curl -I https://api.example.comを実行します。cURLは接続できるのにNode.jsが接続できない場合、問題はNode.jsのバージョンか、特定のライブラリの設定にある可能性が高いです。- DNSキャッシュを実装する: Node.jsはデフォルトでリクエストごとに新しくルックアップを実行します。毎秒1,000回以上のリクエストが発生する高負荷下では、DNSリゾルバを圧倒してしまうことがあります。dnscacheのようなパッケージを使用して結果を保存し、リクエストあたりのレイテンシを10〜20ms削減しましょう。## 予防とベストプラクティス本番環境からENOTFOUNDを排除するために、以下のルールに従ってください。
  • フォールバック・リゾルバ: 地元のプロバイダーが不安定な場合に備え、サーバーの/etc/resolv.confでGoogle (8.8.8.8) や Cloudflare (1.1.1.1) を使用するように設定します。- スマートなネットワーク設計: マイクロサービスをセットアップする際、CIDRブロックの重複を避けてください。私はネットワーク計算に間違いがないか再確認するために、ToolCraftのサブネット計算機を使用しています。これにより、AWSやAzureにデプロイする前にゲートウェイや内部IPレンジが衝突しないようにしています。- 堅牢なエラーハンドリング: ネットワークコールをそのままにしないでください。必ずtry/catchブロックで囲みましょう。ENOTFOUNDが発生した場合は、アプリを完全にクラッシュさせるのではなく、リトライ戦略を実行するか、ユーザーに適切に通知するようにします。## 学んだ教訓getaddrinfo ENOTFOUNDエラーがコードのバグであることは稀です。通常、それはOS、Dockerネットワーク、あるいは設定ファイルといった環境の同期が取れていないことを示すシグナルです。ホスト名を検証し、環境変数の読み込みを確認し、コンテナ間の通信の仕組みを理解することで、これらのエラーを解消し、機能の開発に戻ることができます。

Related Error Notes