答案是DNS解析本身正常,但Composer未走预期DNS路径或PHP环境未继承DNS配置。nslookup通而Composer报错,说明系统DNS可用,问题出在PHP cURL绕过系统DNS、WSL与宿主机DNS独立、Docker容器未配置--dns、PHP未读取hosts(尤其Windows)、或中文编码导致gethostbyname()静默失败。

nslookup 能通但 Composer 仍报 “Could not resolve host”?
说明 DNS 解析本身没问题,但 Composer 没走你预期的 DNS 路径——常见于 PHP cURL 扩展绕过系统 DNS、或启用了 CURLOPT_DNS_USE_GLOBAL_CACHE = false 导致缓存失效。Linux/macOS 下可运行 php -i | grep -i curl 查看是否启用了自定义 DNS 行为;Windows 用户注意 WSL 和宿主机 DNS 独立,nslookup 在 PowerShell 里通,不代表 WSL 里的 PHP 也能解析。
内网域名(如 dev.api.local)在 Composer 中无法解析
Composer 默认只处理 packagist.org、github.com 这类公网仓库域名,对自建私有包源使用的内网域名(如 repo.internal.company)不做特殊适配,完全依赖 PHP 底层的 getaddrinfo() 调用结果。若该域名在宿主机 /etc/hosts 或 DNS 服务器中已配置,但 Composer 仍失败,大概率是:
- PHP 运行环境(如 Docker 容器、PHP-FPM)未继承宿主机 DNS 配置:Docker 启动时没加
--dns=10.0.0.1,或容器内/etc/resolv.conf被覆盖 - 内网 DNS 服务器未响应反向查询,或返回 IPv6 地址而 PHP cURL 编译时禁用了 IPv6 支持
- 中文环境某些终端(如 Windows Terminal + ConPTY)会截断 DNS 查询响应,改用 CMD 或 PowerShell 原生窗口重试
hosts 文件写对了,为什么 Composer 还是连不上内网源?
因为 Composer 不读取 hosts 文件——它调用的是 PHP 的 stream 或 cURL 扩展,而这些扩展在 Linux/macOS 上默认使用 glibc 的 getaddrinfo(),该函数会读 hosts,但 Windows 下 PHP 的 Winsock 实现有时跳过 hosts 直接走 DNS。验证方式很简单:
- 先用
php -r "print_r(gethostbynamel('dev.api.local'));"看 PHP 是否能解析 - 如果返回空数组,说明 PHP 层根本没查到,不是 Composer 的锅
- Windows 用户必须以管理员权限编辑
C:\Windows\System32\drivers\etc\hosts,且保存后执行ipconfig /flushdns,否则旧缓存还在
中文路径或环境变量含中文导致 DNS 解析异常?
极少但真实存在:某些旧版 PHP(7.4 以下)在 Windows 上解析 hosts 时,若系统区域设置为中文简体且 hosts 文件保存为 UTF-8 with BOM,gethostbyname() 会静默失败。解决方法只有两个:
- 用记事本另存为 ANSI 编码(非 UTF-8),再写入
127.0.0.1 dev.api.local - 升级到 PHP
8.0+,它对 UTF-8 hosts 文件支持更健壮
别忽略这一点:哪怕 nslookup 和 ping 都显示正常,PHP 层仍可能因编码问题卡在解析阶段,且不报错,只默默返回 false。


















