私有仓库部署失败主因是未禁用 packagist.org fallback、url 缺末尾斜杠或 satis 生成的 packages.json 不可直接 get;需确保 php ≥ 7.3、启用必需扩展、composer v2、satis 配置正确、web 服务指向 web/ 目录、客户端 composer.json 显式声明仓库并禁用 packagist.org。

私有仓库部署失败,90% 是因为没关 packagist.org fallback、URL 少了末尾斜杠、或 Satis 生成的 packages.json 不可直接 GET。
确认服务器 PHP 环境和 Composer 版本
Composer 是 PHP 脚本,不是独立二进制,必须确保:
- PHP ≥ 7.3(Laravel 8+、Symfony 6+ 已强制要求),运行
php -v验证 - 必需扩展已启用:
openssl、curl、mbstring、json、zip,用php -m | grep -E 'openssl|curl|mbstring|json|zip'检查 - Composer 必须是 v2(v1 已于 2022 年停更),运行
composer --version;若显示 1.x,立刻卸载后重装官方脚本版 - 别用
yum install composer或apt install composer,系统源里的版本普遍滞后且无更新机制
用 Satis 构建静态仓库并部署到 Web 目录
Satis 不依赖数据库,只生成 packages.json 和归档文件,适合企业内网部署。关键点不是“怎么 build”,而是“build 出来的东西能不能被 composer install 直接拉到”:
- 安装 Satis:在服务器上执行
composer create-project composer/satis:dev-main satis --stability=dev --no-interaction - 写好
satis.json,重点检查:
–"repositories"列表里每个"url"必须是真实可访问的 VCS 地址(如https://git.example.com/company/auth.git)
–"require-all": true或明确列出包名(如"company/auth": "*"),空数组或"*/*"不生效
–"archive"配置中"prefix-url"要填你最终部署的 CDN 或 Web 域名(如"https://packages.example.com"),不能留空 - 构建命令必须带输出路径:
php bin/satis build satis.json web/,生成的web/packages.json必须能被 curl 直接拿到:curl -I https://packages.example.com/packages.json返回 200 - Nginx/Apache 的 root 必须指向
web/目录(不是web/packages.json),否则 Composer 会拼出错误 URL
项目中正确引用私有仓库
客户端项目(即使用私有包的那个 PHP 项目)的 composer.json 必须同时满足三项,缺一不可:
- 显式声明仓库类型为
composer,URL 以/结尾:"url": "https://packages.example.com/"(少一个斜杠就 404) - 必须添加
"packagist.org": false这一行——不是注释掉,也不是放在repositories里,而是和repositories同级的顶层字段 - 确保私有包的
name(如company/auth)和version(如dev-main或1.2.0)与 Satis 扫描到的完全一致;Satis 不会自动补全未声明的依赖,也不会提示“跳过”,只会静默忽略 - 如果私有包本身 require 其他私有包,得在
satis.json的"repositories"或"require"中一并列出,否则composer install会报Package xxx is not available
Artifactory 或 Nexus 用户注意仓库类型陷阱
不是所有“能存文件”的仓库都兼容 Composer:
- Artifactory 上必须创建 Native Composer 类型 的 Local/Remote/Virtual 仓库;Generic、Maven、Npm 类型仓库即使 URL 正确,也会在
composer install时抛出Invalid repository type或元数据解析失败 - Remote 仓库的
"URL"字段填的是上游源(如https://packagist.org),不是你自己的 Git 地址;Virtual 仓库的"Repositories"列表里,必须把已启用的 Composer 类型本地/远程仓库拖进去,并勾选Enable Default Deployment Repository,否则composer publish会拒绝上传 - URL 末尾的
/绝对不能省——https://artifactory.example.com/artifactory/api/composer/my-repo和https://artifactory.example.com/artifactory/api/composer/my-repo/是两个不同路径,后者才符合 Composer 协议规范
最常被忽略的其实是权限链路:Git 仓库 → Satis 构建机 → Web 服务 → 项目机器,任意一环认证缺失或网络阻断,都会导致 packages.json 拉不到,而 Composer 默认 fallback 行为会让问题看起来像“配置没错但就是不生效”。











