◀ 12.

php_network_getaddresses: getaddrinfo failed: Name or

▶
この記事の要点
  • PHP が接続先のホスト名を IP アドレスに変換(名前解決)できなかったときのエラー
  • まず疑うのはホスト名の書き間違い。http:// 付きの URL をホスト名欄に渡していないかも確認
  • Docker 環境で DB に繋がらない場合は、DB_HOST がサービス名と一致しているか・同じネットワークにいるかを確認
  • サーバー全体で名前解決できないなら /etc/resolv.conf の DNS 設定を見直す
  • getent hosts ホスト名 で PHP と同じ仕組みの名前解決を試せる

エラー内容

php_network_getaddresses: getaddrinfo failed: Name or service not known

PHP のバージョンによっては、getaddrinfo for example.com failed のように失敗したホスト名が含まれます。また、同じ原因でも OS や状況によって後半の文言が変わります。

後半の文言意味
Name or service not knownそのホスト名は存在しない(と DNS が答えた)。書き間違いや未登録
Temporary failure in name resolutionDNS サーバーに問い合わせできなかった。ネットワークや DNS 設定の問題
No such host is knownWindows での「存在しない」

発生条件

PHP から外部のホストへ接続する処理で発生します。

  • file_get_contents('https://...') や fopen() で URL を開いたとき
  • fsockopen() や stream_socket_client() で接続したとき
  • PDO・mysqli でデータベースに接続したとき(Laravel では SQLSTATE[HY000] [2002] php_network_getaddresses: ... という形で出ます)
  • SMTP サーバーや Redis への接続時

原因と対処法

1. ホスト名の書き間違い・書式の誤り

最も多い原因です。スペルのほか、ホスト名だけを書く欄にスキームやパスを付けていないか確認します。

// NG: ホスト名の欄に URL を渡している
$db = new mysqli('http://db.example.com', 'user', 'pass', 'app');

// OK: ホスト名だけを渡す
$db = new mysqli('db.example.com', 'user', 'pass', 'app');
$pdo = new PDO('mysql:host=db.example.com;dbname=app;charset=utf8mb4', 'user', 'pass');

設定値の前後に空白や改行が紛れ込んでいるケースもあります。.env の値をコピーしたときなどに注意します。

2. Docker でサービス名が合っていない

Docker Compose の環境では、コンテナ同士はサービス名で名前解決します。docker-compose.yml のサービス名が db なら、アプリ側の接続先も db にします。localhost や 127.0.0.1 はアプリのコンテナ自身を指すので、DB コンテナには繋がりません。

# .env(Laravel の例)
DB_HOST=db

また、相手のコンテナが起動していない・別のネットワークに属している場合も解決できません。docker compose ps で状態を確認します。

3. サーバーの DNS 設定

どのホスト名も解決できない場合は、サーバー自体の DNS 設定を疑います。Linux では /etc/resolv.conf に問い合わせ先の DNS サーバーが書かれています。

# /etc/resolv.conf の例
nameserver 8.8.8.8
nameserver 1.1.1.1

NetworkManager や systemd-resolved が管理している環境では、このファイルを直接編集しても再起動などで上書きされます。nmcli や /etc/systemd/resolved.conf など、その環境の管理方法で設定してください。クラウドの仮想マシンでは、提供元が用意した DNS を使う設定が既定になっていることが多いので、変更前に元の値を控えておきます。

4. 成功したり失敗したりする(不定期に発生する)

本来なら適切な DNS サーバーを設定すれば解決する問題ですが、成功したり失敗したりと不定期に起こる場合は、DNS サーバーの一時的な応答遅延・障害や、ネットワークの不安定さが考えられます。応急処置としてサーバーを再起動すると直ることがありますが、これはネットワーク関連のサービスや名前解決のキャッシュがリセットされるためです。再発を防ぐには次のような対策をとります。

  • nameserver を複数指定して、1 台が応答しないときに切り替わるようにする
  • /etc/resolv.conf の options timeout:2 attempts:3 などで、タイムアウトと再試行回数を調整する
  • アプリ側で、外部 API の呼び出しに再試行(リトライ)処理を入れる
  • 頻繁に接続する固定の相手なら、/etc/hosts への記載も選択肢(IP 変更に追従できない点に注意)

確認方法

PHP の外で名前解決を試し、問題が PHP 側かサーバー側かを切り分けます。

# OS の名前解決(/etc/hosts も含む。PHP と同じ仕組み)
getent hosts example.com

# DNS サーバーへ直接問い合わせる
dig example.com
nslookup example.com

# PHP から解決できるか(失敗するとホスト名がそのまま返る)
php -r 'var_dump(gethostbyname("example.com"));'

# Docker の場合はアプリのコンテナ内で実行する
docker compose exec app getent hosts db

getent では成功するのに PHP だけ失敗する場合は、PHP-FPM の実行環境(chroot の設定など)や、Web サーバー経由と CLI で実行環境が違う可能性を調べます。逆に getent でも失敗するなら、PHP ではなくサーバーの DNS 設定かネットワークの問題です。

関連

Post Share
子ページ

子ページはありません

同階層のページ
  1. Fatal error: Maximum execution time of 30 seconds exceeded in...
  2. Fatal error: Uncaught Error: Cannot use object of type stdClass as array in ...
  3. Warning: Use of undefined constant ... - assumed '...' (this will throw an Error)
  4. ERROR: Call to undefined method Maatwebsite\Excel\Excel::load()
  5. Maximum execution time of 30 seconds exceeded
  6. Your requirements could not be resolved to an installable set of packages. ... To enable extensions, verify that they are enabled in your .ini files:
  7. could not find driver
  8. the requested PHP extension mbstring is missing from your system.
  9. the requested PHP extension dom is missing from your system.
  10. A non well formed numeric value encountered
  11. Warning: Cannot modify header information - headers already sent by ...
  12. php_network_getaddresses: getaddrinfo failed: Name or service not known
  13. XMLWriter::openUri(): Unable to resolve file path
  14. Object of class stdClass could not be converted to string
  15. Class 'Google_Service_Youtube' not found