离线环境必须彻底切断Composer所有网络触发点,仅设COMPOSER_DISABLE_NETWORK=1不够,因元数据校验仍会请求repo.packagist.org;须全局及项目级禁用默认源、删除公网仓库配置,并验证composer install -v无Downloading日志。

离线环境不是“配个参数就能用”,而是必须切断所有网络触发点,让 Composer 完全不尝试发任何 HTTP 请求——否则哪怕 vendor 目录齐全,composer install 也会卡在 Could not fetch https://repo.packagist.org/packages.json。
为什么 COMPOSER_DISABLE_NETWORK=1 单独不够
这个环境变量只拦住下载动作,但拦不住元数据校验逻辑。只要 composer.json 或全局配置里还留着 repo.packagist,Composer 就会在 install 阶段主动拼出 URL 去请求,哪怕只是做版本合法性检查。
- 必须运行
composer config --global repo.packagist false彻底禁用默认源(注意是false,不是空字符串或null) - 检查项目级配置:
composer config repo.packagist输出应为空;若返回composer https://packagist.org,说明被composer.json里的repositories字段覆盖了 - 删掉项目
composer.json中所有含"type": "composer"且"url"指向公网的条目,尤其警惕{"packagist.org": false}这种伪禁用写法——它反而会激活 fallback 行为 - 验证方式:执行
composer install -v,日志里不能出现任何Downloading https://repo.packagist.org/
离线机上怎么装新包(比如私有组件)
composer require 在离线机上完全不可用——它强制联网查包名、解析版本约束、校验依赖树。唯一可行路径是提前在联网机上用 path 类型仓库注入。
- 在联网机上把私有包(如
myorg/utils)放在本地路径./packages/myorg-utils,确保其含完整composer.json和src/ - 项目
composer.json中添加:{ "repositories": [ { "type": "path", "url": "./packages/myorg-utils" } ] } - 联网机上跑
composer require myorg/utils:dev-main,它会软链接到本地路径,生成带"dist": {"type": "path", "url": "..."}的composer.lock - 把整个项目(含
vendor/、composer.lock、composer.json)拷到离线机,再执行COMPOSER_DISABLE_NETWORK=1 composer install --no-plugins --no-scripts --no-autoloader
composer create-project 离线必失败,别试
这个命令本质是 git clone + composer install 两步合并,第一步就硬编码访问 Packagist 元数据。加 --offline 无效,COMPOSER_DISABLE_NETWORK=1 也拦不住。
- 正确做法:在联网机上用
git clone拉骨架(如topthink/think),删掉自带composer.lock,再执行composer install --no-dev --prefer-dist --no-scripts --no-plugins --optimize-autoloader - 打包整个目录(含已填充的
vendor/),拷入离线机后执行:composer config --global cache-dir /dev/null COMPOSER_DISABLE_NETWORK=1 composer install --no-plugins --no-scripts --no-autoloader composer dump-autoload -o
- 漏掉最后一句
composer dump-autoload -o,90% 概率报Class not found—— 因为--no-autoloader跳过了 autoload 重建,而离线机上没现成的vendor/autoload.php映射
Satis 仓库输出不是“服务”,是静态文件集
Satis 生成的是一堆 packages.json 和 ZIP 包,没有后台进程。部署时容易忽略三个硬性条件:
-
satis.json中必须设"require-dependencies": true,否则只拉顶层包,子依赖缺失会导致Class not found静默失败 -
"archive"必须启用,且"prefix-url"填你内网 Web 服务的真实地址(如http://packages.internal/dist),否则packages.json里dist.url仍指向公网 - 离线机访问 Satis 仓库前,要确认 Web 服务能直接返回
packages.json(HTTP 200),且 ZIP 包路径可直链下载(不要跳登录页、不要 403)











