エラーの内容
スクリプト、CIパイプライン、またはターミナルでcurlコマンドを実行すると、以下のエラーが表示されます:
curl: (6) Could not resolve host: api.example.com
終了コード6はDNS解決に失敗したことを意味します。curlはホスト名に対応するIPアドレスを見つけられず、接続を試みることすらできませんでした。サーバー自体は正常に動作している可能性があります。あなたのマシンがホスト名を解決できないだけです。
原因
- DNSサーバーに到達できないか、設定が間違っている(
/etc/resolv.confが無効なアドレスを指している) - ネットワーク接続が全くない(リンクがダウンしている)
- ホスト名のタイポ — スクリプトでは思いのほかよくある問題です
- VPNまたはプロキシがDNSクエリをブロックしている
- 企業のファイアウォールがアウトバウンドのUDPポート53をブロックしている
- DockerまたはWSL2がホストのDNS設定を引き継いでいない
/etc/hostsに古い、または競合するエントリがある
ステップ1 — DNSの問題か、ネットワーク自体の問題かを確認する
まず最もシンプルな確認から始めましょう:
ping -c 3 8.8.8.8
3回のpingが成功すれば、ネットワークリンクは正常です。次のステップに進みましょう。3回すべて失敗する場合はネットワークの問題です — まずそちらを修正してください。DNS関連の対処法では解決できません。
ネットワークが正常であることを確認したら、DNSを直接テストします:
nslookup api.example.com
# または
dig api.example.com
nslookupからSERVFAILまたはconnection timed outが返る場合は、リゾルバーが壊れています。ステップ2に進んでください。nslookupは成功するのにcurlが失敗する場合は、nsswitch.confのエッジケースです — ステップ4に進んでください。
ステップ2 — DNSリゾルバーの設定を確認する
cat /etc/resolv.conf
正常なファイルには、少なくとも1つの有効なネームサーバーが含まれているはずです:
nameserver 8.8.8.8
nameserver 1.1.1.1
ファイルが空、応答しないnameserver 127.0.0.53、または到達できないプライベートIPが設定されている場合、終了コード6が発生します。
明示的なリゾルバーを使った簡易確認:
curl --dns-servers 8.8.8.8 https://api.example.com
これで解決した場合、デフォルトのリゾルバーが問題です。/etc/resolv.confを修正しましょう:
# 一時的な設定 — 再起動またはネットワーク再起動でリセットされます
sudo bash -c 'echo "nameserver 8.8.8.8" > /etc/resolv.conf'
sudo bash -c 'echo "nameserver 1.1.1.1" >> /etc/resolv.conf'
systemd-resolvedを使用するUbuntuでは、永続的な修正方法が異なります:
sudo systemctl enable --now systemd-resolved
sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
ステップ3 — ホスト名のタイポを除外する
スクリプトではこれが特に起こりやすいです。余分なダッシュ、ドットの欠落、間違ったTLD — これだけで終了コード6が発生し、原因が全くわからないことがあります。
# 信頼できる公開リゾルバーに問い合わせる
nslookup api.example.com 8.8.8.8
GoogleのリゾルバーからNXDOMAIN(Non-Existent Domain)が返る場合、そのホスト名は存在しません。DNS設定の問題ではなく、ドメイン自体が間違っています。環境変数を確認してください:
echo "$API_BASE_URL"
curl -v "$API_BASE_URL/health"
二重スラッシュ、末尾のスペース、または未設定のまま空文字列に展開された環境変数に注意してください。
ステップ4 — VPNまたはプロキシの干渉を確認する
VPNは独自のDNSサーバーをプッシュしますが、そのプッシュが問題を引き起こすことがあります。実際にクエリを解決しているものを確認しましょう:
resolvectl status # systemd-resolvedシステムの場合
scutil --dns # macOSの場合
VPNを切断してcurlを再実行してください。解決した場合、VPNのDNS設定が原因です。VPNクライアントのスプリットDNS設定を調整するか、ネットワーク管理者に相談してください。
企業のHTTPプロキシはDNSをあなたの代わりに処理するため、curlにプロキシを認識させる必要があります:
# プロキシを明示的に指定する
curl -x http://proxy.corp.example.com:3128 https://api.example.com
# またはセッション全体でエクスポートする
export https_proxy=http://proxy.corp.example.com:3128
curl https://api.example.com
ステップ5 — Dockerコンテナ内のDNSを修正する
コンテナはホストのDNSを自動的に引き継ぎません。まず確認してみましょう:
docker run --rm alpine nslookup api.example.com
失敗した場合は、実行時にDNSを指定します:
docker run --rm --dns 8.8.8.8 alpine nslookup api.example.com
すべてのコンテナに永続的な設定を適用するには、/etc/docker/daemon.jsonを編集します:
{
"dns": ["8.8.8.8", "1.1.1.1"]
}
sudo systemctl restart docker
ステップ6 — /etc/hostsの競合を確認する
grep api.example.com /etc/hosts
ここに古いエントリがあると、DNSより優先されます。curlはハードコードされたIPに接続しようとしますが、そのIPが間違っていたり、すでに廃止されていたり、ローカル開発環境を指している可能性があります。古い行を削除または修正してください。
ステップ7 — ファイアウォールによるUDPポート53のブロックを確認する
一部の企業環境やクラウド環境では、UDPポート53へのアウトバウンドDNSトラフィックを静かにドロップします。TCPに切り替えてテストしましょう:
dig +tcp api.example.com @8.8.8.8
TCPでは解決できるが、通常のdig api.example.comがハングする場合、UDPポート53がフィルタリングされています。対処法としては、DNS-over-HTTPSを使用するか、ネットワークチームにポートの開放を依頼してください。
確認 — 修正が正しく機能したかを検証する
# 1. DNSが正常に解決されることを確認
nslookup api.example.com
# 期待する結果:実際のIPアドレスを含む1行以上のAddressが表示される
# 2. curlが接続できることを確認
curl -v https://api.example.com/
# 確認ポイント:"* Connected to api.example.com (x.x.x.x)"
# NGの場合:"Could not resolve host"
# 3. スクリプトから実行する場合は、終了コードを明示的に確認する
curl -sf https://api.example.com/health && echo "OK" || echo "FAILED: $?"
再発防止のヒント
curlに渡す前にホスト名を検証する:
HOST=$(echo "$API_BASE_URL" | awk -F[/:] '{print $4}')
if ! nslookup "$HOST" > /dev/null 2>&1; then
echo "ERROR: Cannot resolve $HOST — check DNS or the URL" >&2
exit 1
fi
curl "$API_BASE_URL/data"
一時的なDNS障害に対してリトライロジックを追加する:
curl --retry 3 --retry-delay 2 --retry-connrefused https://api.example.com
ローカルテスト時は--resolveを使ってDNSを完全にバイパスする:
# /etc/hostsを変更せずに特定のIPに固定する
curl --resolve api.example.com:443:93.184.216.34 https://api.example.com
問題がDNS設定ではなくネットワークルーティングにある場合、たとえば特定のサブネットからどのリゾルバーに到達できるかを調べる場合は、ToolCraftのIPサブネット計算ツールを使用すると、ローカルに何もインストールせずにサブネットとCIDR範囲を計算できます。

