Composer 不支持镜像代理转发,仅支持换源或 HTTP 代理;换源需完整实现 Composer 协议的镜像服务,代理仅控制请求出口,不改写地址;真正按需缓存需 Satis、Private Packagist 或 Artifactory 等中间服务。

Composer 本身没有“镜像代理转发”功能,所谓“内网福音”是误传——它只是支持换源和走 HTTP 代理,两者不能混用,也不能让一个内网地址自动转发请求到 packagist.org。
composer config -g repo.packagist 是换源,不是代理转发
执行 composer config -g repo.packagist composer https://your-intranet-mirror.com 后,Composer 会把所有元数据请求(如 packages.json、provider-*.json)发往你指定的地址,但前提是这个地址必须是一个完整实现 Composer 协议的镜像服务(比如 Satis、Toran Proxy、Artifactory 或 Packagist 镜像站),而不是一个简单的反向代理。
常见翻车点:
- 直接用 Nginx 反代
https://packagist.org并填进repo.packagist→ 请求能通,但返回 404 或空响应,因为 packagist.org 不允许跨域直连,且其 CDN 和动态路由无法被简单反代 - 镜像地址末尾漏掉斜杠(如
https://your-mirror而非https://your-mirror/)→ Composer 内部拼 URL 时变成https://your-mirrorpackages.json,直接 404 - 用了 HTTP 地址但没加
--allow-http→ Composer 2.0+ 默认拒绝,静默 fallback 或报错
http-proxy 和 https-proxy 是真代理,但不处理“镜像逻辑”
http-proxy 和 https-proxy 配置只控制底层 cURL 请求的出口,不改变 Composer 的行为逻辑。它不会帮你把对 https://your-intranet-mirror.com 的请求再转给外网,也不会把对 https://packagist.org 的请求改写成别的地址。
关键事实:
-
https-proxy的值必须是http://开头(哪怕代理本身监听 HTTPS),否则会被忽略 - 如果镜像站用了自签名证书,
composer config -g secure-http false才能绕过 TLS 校验,否则卡在 cURL error 60 - 设了代理后仍连不上?先用
curl -x http://127.0.0.1:8080 -I https://your-intranet-mirror.com/packages.json确认代理链路是否通
真正能“转发”的方案只有两种,且都得自己搭服务
如果你确实需要“请求进来 → 判定是否命中缓存 → 没有就去外网拉 → 存一份再返回”,这不是 Composer 能干的事,得靠中间服务:
-
Satis:静态生成 JSON + ZIP,适合离线或低频更新场景;必须提前运行
php bin/satis build satis.json web/把所有递归依赖(包括require-dev和间接依赖)全拉下来,否则内网composer install仍会失败 - Toran Proxy / Private Packagist / Artifactory:带缓存代理能力的商业或开源服务,支持按需拉取 + 自动缓存 + 私有包托管;部署复杂,但能真正实现“首次访问触发回源,后续走本地”
注意:Satis 不是代理,它不实时转发;Toran 已停止维护,Private Packagist 是付费方案;Artifactory 需要 PHP 仓库插件支持,配置门槛高。
artifact 源是最轻量的“伪转发”,但只适用于一次性交付
当你完全断网、又不想搭服务时,"type": "artifact" 是唯一不发网络请求的方式:
- 在外网机器执行
composer install --no-dev --prefer-dist --no-autoloader --no-scripts,触发 ZIP 包下载到~/.composer/cache/files/ - 把整个
files/目录拷进内网,在项目下建artifacts/并放进去 - 项目
composer.json加:{"repositories": [{"type": "artifact", "url": "./artifacts/"}]}
限制很明确:ZIP 包必须和 composer.lock 中记录的 SHA256 完全一致;新增依赖必须重新在外网打包;不支持 Git 分支、dev 版本、zip 包缺失任一文件都会中断安装。
最常被忽略的一点:镜像站或 artifact 目录里缺的从来不是主包,而是它的子依赖(比如 monolog/monolog 依赖的 psr/log)。光看 composer.json 的 require 列表远远不够,必须确保整条依赖树都被覆盖。











