COMPOSER_DISABLE_NETWORK=1是离线模式硬性开关,不设则所有参数无效;它强制跳过远程元数据请求,否则即使vendor和lock完整也会报Could not fetch packages.json等错误。

COMPOSER_DISABLE_NETWORK=1 是离线模式的硬性开关
不设它,所有其他参数都无效。Composer 在 install 阶段会强制请求 https://repo.packagist.org/packages.json,哪怕 vendor/ 和 composer.lock 都完整存在,也会报错退出。
常见错误现象:Curl error 60、Could not resolve host、Could not fetch packages.json——这些不是证书或 DNS 问题,而是网络未真正禁用的信号。
- Linux/macOS:执行前加
COMPOSER_DISABLE_NETWORK=1,如COMPOSER_DISABLE_NETWORK=1 composer install --no-plugins --no-scripts --no-autoloader - Windows CMD:
set COMPOSER_DISABLE_NETWORK=1 && composer install ... - Windows PowerShell:
$env:COMPOSER_DISABLE_NETWORK="1"; composer install ... - 容器环境:Dockerfile 中写
ENV COMPOSER_DISABLE_NETWORK=1,不能只靠RUN临时设置
cache-files-dir 必须显式配置且带 /files 后缀
cache-dir 只是父目录,不控制 ZIP 包存放位置;真正决定离线能否复用的是 cache-files-dir,它必须指向一个含 /files 子路径的绝对路径。
容易踩的坑:composer config --global cache-dir /tmp/composer-cache 看似配了,但 Composer 仍会往默认 ~/.composer/cache/files 写 ZIP,而离线机该路径通常为空。
- 在线机预处理:先
composer config --global --unset cache-dir,再composer config --global cache-files-dir /mnt/offline-cache/files - 验证是否生效:检查
/mnt/offline-cache/files/monolog/monolog/2.10.0.0/monolog-monolog-*.zip是否真实存在 - 离线机上必须复制整个
/files目录(保留层级),并再次运行composer config --global cache-files-dir /your/copied/path/files - 权限问题常被忽略:PHP 进程用户(如
www-data)需对/files目录有read+execute权限,否则静默 fallback 到重下
--no-plugins --no-scripts --no-autoloader 是最小安全组合
这三个 --no- 参数不是“可选优化”,而是防止插件/脚本绕过离线限制的关键防护。例如 phpstan/extension-installer 会在 --no-plugins 外部触发网络调用,post-install-cmd 可能执行 npm install 或远程 API 请求。
注意:--no-autoloader 会让 autoload 文件跳过重建,但运行时必报 Class not found,所以必须紧接着手动补一记:
-
composer dump-autoload -o—— 这步不能省,且必须在install后立即执行 - 若项目含
"type": "path"仓库,确保对应目录下有合法composer.json,且name和version(或dev-master分支标识)完整 -
composer.lock中若存在"source": {"type": "git", ...},离线安装必然失败——这种锁文件天生不支持离线
repo.packagist false 必须全局禁用,不能靠断网代替
很多人以为删掉 composer.json 里的镜像配置或注释掉 repositories 就够了,其实不行。只要全局配置中 repo.packagist 还是 true 或未显式设为 false,Composer 就会在离线时 fallback 尝试连接官方源。
验证方式:composer config --global repo.packagist 应输出 false,而不是 JSON 对象或空值。
- 正确禁用命令:
composer config --global repo.packagist false - 错误做法:
composer config --global --unset repos.packagist(键名错)、composer config --global repositories.packagist false(路径错) - 若项目级
composer.json里有"repositories"块,它会覆盖全局配置,必须同步清理或确保其 type 是path且 url 是本地绝对路径 - 某些 CI 环境(如 GitLab Runner)会自动注入镜像配置,需在 job 脚本开头显式覆盖
离线配置最脆弱的环节不在参数本身,而在“多层配置叠加”:全局 config、项目 config、环境变量、命令行参数之间存在优先级和覆盖逻辑。一旦某一层残留了联网倾向的配置(比如旧的镜像 URL 或未 unset 的 cache-dir),Composer 就可能在你没察觉时悄悄发起 HTTPS 请求。


















