离线环境下Composer安装失败的根本原因是默认只信任远程元数据,不验证本地缓存;必须通过--prefer-dist预下载dist包、显式配置cache-files-dir、禁用packagist回源,并配合artifact仓库或satis镜像,才能让Composer信任并使用本地文件。

离线环境下 Composer 安装失败,不是因为没包,而是它压根不信任本地文件——默认只认远程元数据,composer.lock 里写的 dist.url 一断网就报 Could not fetch,连 ~/.composer/cache/files/ 里的 zip 都不看一眼。
为什么 COMPOSER_DISABLE_NETWORK=1 还报错
这个环境变量只是“禁止发起网络请求”,但不会让 Composer 主动去读缓存或本地 ZIP;它仍会按 composer.lock 中的 dist URL 去校验合法性,发现无法访问就直接失败。关键不在“禁不禁网”,而在“它信不信你给的包”。
-
COMPOSER_DISABLE_NETWORK=1必须配合完整composer.lock+ 所有包已以dist形式落盘到缓存中才有效 - 确认缓存路径:
~/.composer/cache/files/(Linux/macOS)或C:\Users\用户名\AppData\Roaming\Composer\Cache\files\(Windows) - 离线机上必须显式配置缓存路径:
composer config --global cache-files-dir /path/to/cached/files,否则 Composer 会忽略该目录 - 联网机执行
composer install --prefer-dist是前提,否则缓存里只有空壳或 source 包
用 artifact 类型仓库绕过元数据校验
这是最轻量、最可控的离线方案:你提供 ZIP,Composer 只解压、装 autoload,不查任何远程地址。适合依赖版本明确、能提前打包的场景。
- ZIP 文件名必须严格为
vendor/name-version.zip(如monolog/monolog-2.13.0.zip),大小写和分隔符都不能错 - 在项目
composer.json中添加:"repositories": [ { "type": "artifact", "url": "./packages/archives" } ] -
artifact不支持dev-main或分支,composer.lock里若锁的是dev-版本,得先手动改成对应 tag,或用satis生成 dist 包 - 不推荐手动整理 ZIP 目录——容易漏包、命名错位;建议用
composer archive或satis build自动生成
用 satis 构建可离线 HTTP 访问的镜像
这是真正“无感离线”的方案:生成完整的 packages.json + ZIP 包集合,再用本地 HTTP 服务托管,Composer 当它是个普通 Packagist 源用。
- 联网机制作镜像:
php bin/satis build satis.json ./mirror,输出的./mirror就是静态资源集 - 离线机启动本地服务(如 Python:
python3 -m http.server 8000),然后配置:composer config repositories.local-mirror composer http://127.0.0.1:8000 - 必须禁用 packagist 回源:
composer config repositories.packagist false,否则 Composer 仍会在找不到包时 fallback 到packagist.org -
satis默认不包含 dev 包,如需,要在satis.json中加"require-dependencies": true和"require-dev-dependencies": true
composer install 离线失败时最该先检查什么
别急着重打包或换方案,先确认三件事是否都满足——90% 的失败卡在这几步:
-
composer.lock是否存在且未被修改?离线安装必须基于锁定文件,不能只靠composer.json - 所有包是否已通过
--prefer-dist下载?检查缓存目录下是否有对应 ZIP,而非空目录或.git子目录 - 是否执行了
composer config repositories.packagist false?只要这行没关,Composer 就会尝试连packagist.org,哪怕你配了artifact或satis - 运行
composer diagnose,看输出里有没有Warning: The lock file is not up to date或Repository "packagist.org" is not disabled这类提示
离线不是简单复制 vendor 或缓存目录,核心是让 Composer 放弃对远程权威的执念——要么用 artifact 让它只认文件名,要么用 satis 给它一个假的但自洽的 Packagist,否则它永远在等那个收不到的 HTTP 响应。











