composer 完全离线需提前落包到本地并显式配置artifact仓库,仅靠disable-network会报错;必须用./artifacts中含有效composer.json的zip包,require写死完整版本号,且禁用网络时需同时关闭packagist.org并指定artifact源。

必须提前把包文件落到本地,Composer 才能真正跳过网络——它没有“运行时断网重试”机制,只有“不查远程、只扫本地”的明确路径。
用 artifact 仓库直接读 ZIP 包(最合规的离线方式)
这是唯一能让 Composer 完全绕过 HTTP 请求、只靠文件系统扫描安装依赖的方式。它不依赖 Packagist,也不需要 Web 服务,只认 .zip 或 .tar.gz 文件名和内部 composer.json 的 name + version。
- 把所有依赖包的 ZIP 文件(比如
monolog/monolog-2.10.0.zip)统一放进一个目录,例如./artifacts/ - 在项目
composer.json中声明:{ "repositories": [{ "type": "artifact", "url": "./artifacts" }] } -
composer install会自动遍历该目录,匹配require中的包名与版本,解压安装 - ⚠️ 注意:
artifact不支持通配符或模糊版本(如"*"),require中必须写死带小数点的完整版本号(如"monolog/monolog": "2.10.0") - ⚠️ 常见失败:ZIP 包里没包含有效的
composer.json,或name字段拼写与require不一致(大小写、斜杠方向都敏感)
直接复制 vendor/ 目录(最快但最脆弱)
适用于固定环境、极少更新、且源机与目标机 PHP 版本/扩展完全一致的场景。它跳过 Composer 解析过程,本质是“搬运已编译结果”。
- 在联网机器上执行:
composer install --no-dev --optimize-autoloader,确保vendor/autoload.php已生成且类映射扁平化 - 连同
vendor/、composer.lock、composer.json一起拷贝到离线机 - 离线机只需运行:
composer install --no-scripts --no-plugins(仅校验 lock,不触发任何远程行为) - ⚠️ 容易踩坑:
vendor/下的符号链接(symlink)在 Windows 或某些容器中会失效;若目标机路径变了(如从/home/dev/app搬到/opt/app),入口文件中require 'vendor/autoload.php'必须改成绝对路径或显式定义根路径 - ⚠️ 若后续报
Class not found,别重装,先在离线机跑:composer dump-autoload --classmap-authoritative
禁用网络 ≠ 自动用本地(配置陷阱要避开)
设置 COMPOSER_DISABLE_NETWORK=1 或 composer config --global disable-network true 只是“堵住出口”,不会“引导入口”。它不自动启用 artifact 或 path,只是让所有远程请求立刻失败。
- 单独设
disable-network后直接跑composer install,会报错:Could not fetch packages.json——因为默认仍尝试访问packagist.org - 正确做法是:禁用网络 + 显式配置本地源,例如:
"repositories": [{ "packagist.org": false }, { "type": "artifact", "url": "./artifacts" }] -
path类型虽可用,但它只接受源码目录(含composer.json),不能加载 ZIP,不适合预打包分发场景 - 别信“搭个内网 Satis 就算离线”——它仍是 HTTP 服务,一旦 Nginx 挂了、URL 配错了、SSL 不被信任,
composer install照样失败
真正跳过网络的关键不是“关掉联网开关”,而是让 Composer 在解析阶段就确认所有包的物理文件已存在。这意味着你必须在联网机上完成完整构建(install + lock + 缓存/ZIP/目录三选一落地),再把确定性带进内网——漏掉 composer.lock,或 ZIP 包版本对不上,就等于没带钥匙去锁门。










