私有包卡在 packagist.org 是因 composer 默认优先查询该源,即使配置镜像也仅加速公开包;必须在 composer.json 顶层设 "packagist": false 并将 gitlab 私有源(type: "composer"、url 以 / 结尾)置于 repositories 数组首位,且通过权限为 600 的 auth.json 正确注入认证凭据。

为什么私有包总卡在 packagist.org 而不是 GitLab?
不是镜像“干扰”,而是 Composer 默认行为:只要 composer.json 里没显式声明私有源,它就会把所有包(包括 mycorp/auth-sdk)当成 public 包,先查 packagist.org 元数据 —— 即使你配了清华源或阿里云镜像,也只加速 public 包,对私有包完全无效。
现象是:composer install 卡在 Downloading https://repo.packagist.org/p2/mycorp/auth-sdk.json,哪怕你的 GitLab 实例就在同一局域网内。
- 镜像源(如
https://mirrors.tuna.tsinghua.edu.cn/composer/)只缓存 packagist.org 的公开元数据和 dist 包,不代理私有仓库 - GitLab 作为私有 Composer 仓库,必须被显式注册为
"type": "composer"源,且 URL 必须以/结尾(例如https://gitlab.internal.com/api/v4/group/packagist/) - 一旦
composer.json含"repositories"字段,全局镜像(repo.packagist)立即失效 —— 这是静默覆盖,不会报错
怎么让 Composer 正确走 GitLab 而不是镜像?
关键不是“关镜像”,而是让私有源优先级高于 packagist.org,并确保它被正确识别。操作分三步:
- 在项目根目录
composer.json的"repositories"数组里,**第一项**写 GitLab 源,且必须包含"packagist.org": false显式禁用默认源:"repositories": [ { "type": "composer", "url": "https://gitlab.internal.com/api/v4/group/packagist/" }, { "packagist.org": false } ] - URL 末尾的
/不可省略,否则请求会变成/p2/xxx.json并返回 404;GitLab 的 Composer API 端点必须支持packages.json和p2/路径 - 不要依赖全局镜像配置(
composer config -g repo.packagist),它在此场景下无意义;项目级repositories一存在,全局设置就彻底忽略
认证失败常见于 auth.json 权限或域名不匹配
Could not fetch 或 Authentication required 错误,90% 是 auth.json 配置失效,而非网络问题。
-
auth.json文件权限必须为600(Linux/macOS):chmod 600 auth.json,否则 Composer 静默跳过读取 - 域名必须与 GitLab 仓库 URL 的 host 部分**完全一致**:如果仓库 URL 是
https://gitlab.internal.com/...,则auth.json中 key 必须是"gitlab.internal.com",不能是"www.gitlab.internal.com"或带端口如"gitlab.internal.com:443" - 凭据不要硬编码进
composer.json:"url": "https://token:x@gitlab.internal.com"会泄露到 Git 历史;应统一走auth.json或COMPOSER_AUTH环境变量
CI 构建时私有包拉取失败的三个硬坑
本地能跑通,CI 却报 Package not found,往往卡在这三点:
- CI 容器里没有
auth.json,或挂载后权限仍是644—— 需在 CI 脚本开头加chmod 600 $COMPOSER_HOME/auth.json - GitLab 仓库启用了
require explicit package name(Satis/Packagist 类服务常见),此时必须在composer.json的"require"中写全名:"mycorp/auth-sdk": "^1.0",不能靠模糊匹配 - GitLab 实例启用了 IP 白名单,而 CI runner 的出口 IP 不在范围内 —— 这时
curl -I https://gitlab.internal.com/api/v4/group/packagist/packages.json会直接返回 403,Composer 却只报超时
真正麻烦的不是配置多,而是错误信息太笼统;验证链路是否通,永远从 curl 开始,而不是直接改 composer.json。











