离线私有源必须用artifact或path类型,不能通过改repo.packagist.org为本地路径实现;artifact要求ZIP文件名严格为vendor-name-package-name-version.zip、存放于单层目录、内含匹配的composer.json,且必须全局及项目级禁用packagist.org。

离线私有源必须用 artifact 或 path 类型,不能改 packagist.org 地址
改 repo.packagist.org 为本地路径(比如 file:///opt/mirror)根本没用——Composer 仍会尝试 DNS 解析、HTTP HEAD 请求、甚至 fallback 到默认源。真正生效的只有 artifact 和 path 这两种仓库类型,它们从设计上就跳过所有网络探测。
常见错误是误以为加了 "repositories": [{"type": "composer", "url": "file:///..."}] 就算离线了,结果 composer install -v 里依然看到 Downloading https://repo.packagist.org/packages.json —— 那说明 packagist.org 没彻底关掉。
- 全局禁用默认源:
composer config --global repo.packagist false - 检查项目级配置:
composer config repo.packagist输出应为空,不是composer https://packagist.org - 删掉
composer.json里所有指向https://packagist.org的repositories条目
用 artifact 仓库时,ZIP 文件名和结构必须严格匹配 lock 文件
artifact 不查元数据,只按 composer.lock 里的 dist.shasum 和 name+version 去本地目录找 ZIP。文件名错一位、路径多一层、扩展名用 .tar.gz 而非 .zip,都会报 Package not found。
正确格式只有这一种:vendor/name-name-version.zip(注意两个 name 之间是短横线,不是斜杠),例如:monolog/monolog-2.13.0.zip。
- ZIP 内必须含有效
composer.json,且name和version字段要和文件名完全一致(大小写敏感) - 所有 ZIP 放在同一级目录下,不要嵌套子目录(
/opt/artifacts/✔,/opt/artifacts/monolog/✘) - 离线机执行:
composer config repositories.offline '{"type":"artifact","url":"/opt/artifacts/"}'
离线部署前必须验证 composer.lock 与 ZIP 包的完整性
离线安装失败,90% 是因为 composer.lock 里某个包的 dist.shasum 在本地 ZIP 目录中找不到对应文件。这通常发生在联网机下载不全:磁盘满、中断、或用了 --ignore-platform-reqs 导致跳过平台特定包(如 ext-gd 相关依赖)。
验证方法很简单:在联网机执行完 composer install --no-install --prefer-dist 后,运行:
cd vendor/composer/cache/files && find . -name "*.zip" | wc -l
再对比 composer.lock 里 packages 和 packages-dev 的总数。两者不等,说明漏包。
- 补漏方式:手动
composer require vendor/name:version --no-update,再composer update vendor/name --no-dev --with-dependencies - 导出 ZIP 时别漏
packages.json(位于vendor/composer/cache/repo/https---packagist.org/),它提供包名→ZIP 路径映射 - 离线机上用
composer install --no-network前,先确保COMPOSER_DISABLE_NETWORK=1环境变量已设
安全隔离区里不能依赖 vendor 直接复制,必须走 install 流程
直接复制 vendor/ 到隔离区看似快,但隐患极多:autoload.php 里可能硬编码了构建机路径;某些包的 post-install-cmd 脚本(如 Laravel 的 php artisan config:clear)没执行过,缓存未生成;symlink 在不同系统间失效;PHP 扩展 ABI 不兼容(比如 OpenSSL 版本差一级)就会 segfault。
真正安全的做法,是让 composer install 在隔离区内完整跑一次:解压 ZIP、校验 shasum、生成 installed.json、写 autoload 映射——这个过程不联网,但能暴露所有环境不一致问题。
- 命令必须带
--no-plugins --no-scripts --no-autoloader兜底:只校验,不执行,不覆盖 - 校验通过后,再跑一次
composer dump-autoload --classmap-authoritative,生成静态类映射,避开运行时文件扫描 - 如果目标机 PHP 版本或扩展缺失,
composer install会立刻报错,比 runtimeClass not found更早暴露问题











