根本原因是dns污染导致repo.packagist.org被错误解析到非官方镜像ip,引发连接失败或跳转异常;需通过hosts绑定、更换dns或清理残留镜像配置来解决。

为什么 composer install 总是卡在 repo.packagist.org 或跳转到奇怪的镜像站?
根本原因不是 Composer 本身出错,而是本地 DNS 解析被污染,把 repo.packagist.org 错误解析到了国内某个非官方镜像(比如某云、某加速器的 IP),而该镜像未同步或配置异常,导致包下载失败、签名验证报错或无限重试。
典型现象包括:Connection refused、SSL certificate problem、Could not resolve host: repo.packagist.org(但实际能 ping 通)、或 composer install 明明没配镜像却自动走 https://packagist.phpcomposer.com 这类已下线地址。
- 优先检查是否全局设置了镜像:
composer config -g repo.packagist,若输出非{"type": "composer", "url": "https://repo.packagist.org"},说明已被篡改 - DNS 污染常发生在校园网、某些 ISP 或开了“智能 DNS”的路由器下,
nslookup repo.packagist.org返回的 IP 不是151.101.10.217(Fastly CDN 正确出口)就基本坐实 - 不要依赖
composer config -g repos.packagist查看——它可能显示正常,但实际请求仍被 DNS 劫持
绕过 DNS 污染的三种实操方式(按推荐顺序)
核心思路:不让系统查 DNS,直接用可信 IP 或可信解析通道发起 HTTPS 请求。
-
方案一(首选):用
hosts文件硬绑定 —— 在/etc/hosts(Linux/macOS)或C:\Windows\System32\drivers\etc\hosts(Windows)末尾追加:151.101.10.217 repo.packagist.org
。注意:必须用这个 IP(Fastly 官方 CDN 地址),其他镜像 IP 会因证书不匹配失败 -
方案二:换 DNS + 禁用系统代理 —— 临时将网络 DNS 改为
1.1.1.1或8.8.8.8,并确认终端没启用 HTTP 代理(echo $HTTP_PROXY/echo %HTTP_PROXY%应为空);Composer 默认不走系统代理,但某些 shell 配置会意外注入 -
方案三:强制指定 DNS 解析(PHP 7.4+) —— 启动 Composer 时加环境变量:
PHP_EXTRA_CONFIG="--with-curl --enable-opcache" COMPOSER_NO_INTERACTION=1 composer install不起作用;真正有效的是:export CURLOPT_DNS_SERVERS="1.1.1.1"(仅 libcurl ≥ 7.24.0 支持,且需 PHP 编译时启用了 cURL 的 DNS-over-HTTPS 支持,实操中成功率低,仅作备选
镜像配置残留引发的二次污染
很多人修复 DNS 后仍失败,是因为 Composer 的全局或项目级镜像配置没清干净,导致即使 DNS 正常,Composer 仍主动发请求到错误域名。
- 删掉全局镜像:
composer config -g --unset repos.packagist(不是repo.packagist,注意 key 名) - 检查项目根目录下的
composer.json,确认没有"repositories"字段覆盖了 packagist - 清除 Composer 缓存:
composer clear-cache,否则旧镜像的元数据可能还在本地缓存里继续干扰 - 验证是否生效:
composer config -g repos.packagist应返回空;再跑一次composer show -p,观察 URL 是否变成https://repo.packagist.org
CI/CD 环境中的隐形陷阱
GitHub Actions、GitLab CI 或 Docker 构建时,DNS 污染更隐蔽——基础镜像自带的 /etc/resolv.conf 可能预设了污染 DNS,且无法修改 hosts。
- 在
.gitlab-ci.yml或workflow中加一步预检:curl -I https://repo.packagist.org/packages.json | head -1
,若返回302或指向非packagist.org域名,说明 DNS 被劫持 - Docker 构建时,用
--dns 1.1.1.1启动容器;GitHub Actions 可加env: { COMPOSER_HOME: "/tmp/composer" }避免继承缓存,再配合run: echo '151.101.10.217 repo.packagist.org' | sudo tee -a /etc/hosts - 不要在 CI 脚本里执行
composer config -g—— 多个 job 并行时可能相互覆盖配置,导致偶发失败
最麻烦的不是 DNS 本身,而是它和 Composer 镜像配置、HTTP 代理、CI 缓存层层叠加,一个环节漏查,问题就复现。动手前先 nslookup repo.packagist.org 和 composer config -g repos.packagist 两行命令,比瞎试更快定位。











