必须用Satis构建静态镜像,因纯离线环境无法联网,而Satis生成packages.json和ZIP包,使Composer能正常解析依赖、执行require/update等操作,且结构兼容Composer 2+ metadata-url协议。

纯离线环境不能靠改 hosts 或设系统代理让 Composer“假装联网”,它会直接报 Connection refused 或卡在 Loading composer repositories;真正可行的路径只有一条:用 satis 构建静态包镜像,并让 Composer 认为那个本地 HTTP 服务就是 packagist.org。
为什么必须用 Satis 而不是直接拷贝 vendor
直接拷贝 vendor/ 只能解决“已有项目运行”问题,但无法支持:composer require 新包、composer update 升级、生成新的 composer.lock。Satis 生成的是完整元数据(packages.json、各包 ZIP、版本索引),让 Composer 的依赖解析器能照常工作。
- Satis 输出的
web/目录里包含packages.json和按命名空间组织的 ZIP 包,结构与 Packagist 官方一致 - Composer 2+ 默认启用 metadata-url 模式,只请求实际需要的包片段,Satis 生成的 JSON 正好匹配该协议
- 若跳过 Satis,手动拼
packages.json极易出错:字段缺失、hash 不对、version 约束格式错误都会导致Your requirements could not be resolved
构建 Satis 镜像时的三个关键配置点
在有网机器上执行 satis build 前,satis.json 必须显式控制包范围和输出行为,否则可能漏包或生成无效结构。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
"require-all": true不够安全——它只拉取repositories中声明源里的包,若你项目用了 GitHub 上未收录到 Packagist 的私有库,需额外加{"type":"vcs","url":"https://github.com/xxx"}到repositories数组 -
"output-dir"必须是空目录,否则旧 ZIP 文件残留会导致composer install解压失败(报错类似zip: not a valid zip file) - 务必加上
"archive": {"format": "zip", "skip-dev": true},否则 Satis 默认不打包 ZIP,离线机执行composer install时会因找不到 dist 包而 fallback 到 source,触发 git clone —— 这在离线环境必然失败
离线机上 composer config 的致命细节
配置错一个字符,Composer 就会静默回退到默认源,然后卡死或报 Could not fetch packages。
- 先彻底禁用默认源:
composer config -g repo.packagist false(注意是false,不是null或空字符串) - 添加本地源时,URL 末尾**不能有斜杠**:
composer config -g repos.packages composer http://localhost:8000(写成http://localhost:8000/会导致请求/packages.json/,404) - 验证是否生效:
composer config -g repos输出应只有你刚加的那一条,且repo.packagist显示为false;如果还看到packagist.org,说明config -g没生效或被项目级配置覆盖
HTTP 服务启动与路径可访问性验证
很多问题其实卡在最底层:离线机根本没跑起来一个能返回 packages.json 的 HTTP 服务。
- 推荐用 Python 快速起服务:
python3 -m http.server 8000(Python 3.7+ 自带),确保当前目录是 Satis 生成的web/ - 必须在离线机本地验证:
curl http://localhost:8000/packages.json返回 200 且含{"packages":{}}结构才算通过;仅在另一台机器 curl 成功不等于 Composer 能访问 - 如果用 Nginx,确认 root 配置指向
web/目录,且location /块里有try_files $uri $uri/ =404;,否则 ZIP 包路径会 404
最关键的遗漏点是:Satis 构建时不会自动包含你项目 composer.lock 里引用的 dev-only 包(如 phpunit/phpunit),除非你在 satis.json 里显式 "require-dependencies": true 并把 --no-dev 从构建命令里去掉——但这样会显著增大镜像体积。生产离线环境通常应区分构建机与运行机,dev 包只在构建阶段需要。

















