satis 是内网离线 composer 私有仓库最可控方案,但需彻底禁用 packagist 默认源、启用 require-dependencies 和 archive、同步完整 cache-dir、确保 php 环境一致,并通过 path/artifact 方式新增私有包。

内网离线环境下,Composer 私有仓库不能靠“配个镜像地址”就跑起来——必须切断所有网络触发点,并确保元数据、dist 包、autoload 三者在本地闭环。Satis 是最可控的方案,但它的输出不是开箱即用的“服务”,而是一组静态文件;Artifact 和 path 类型仓库则更适合零星补包或开发联调,无法替代完整镜像。
为什么 Satis 生成的仓库在离线机上仍报 Could not fetch packages.json
错误不是因为没连上服务器,而是项目 composer.json 或全局配置中还残留着 repo.packagist 的 fallback 源。Satis 生成的是 packages.json,但 Composer 默认仍会尝试请求 https://repo.packagist.org/packages.json 做兜底校验。
- 必须运行
composer config --global repo.packagist false彻底禁用默认源 - 检查项目级配置:
composer config repo.packagist输出应为空,不能是composer https://packagist.org - 项目
composer.json中的repositories字段不能包含任何指向https://packagist.org的条目 - 验证方式:
composer install -v看日志里是否还有Downloading https://repo.packagist.org/packages.json
Satis 构建时必须启用 require-dependencies 和 archive
只设 "require-all": true 不够,它只拉取直接声明的包,不递归抓取依赖树。离线环境里缺一个子依赖,composer install 就会静默失败或报 Class not found。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
"require-dependencies": true:强制解析并拉取所有依赖项(包括 dev 依赖,若需) -
"archive": { "directory": "dist", "format": "zip" }:生成可离线分发的 ZIP 包,而非仅保留 Git 引用 -
"prefix-url"必须填成你内网 Web 服务的真实地址(如http://packages.internal/dist),否则packages.json里的 dist URL 会指向公网 - 构建命令必须带
--no-interaction,避免卡在交互式提示上
离线机部署后必须重设 cache-dir 并验证 repo 目录结构
即使把 Satis 输出的 web/ 目录整个拷到 Nginx 根路径下,Composer 仍可能因缓存目录错位而反复尝试联网——它会在默认缓存路径下找 repo/https---packagist.org/packages.json,找不到就报错。
- 先查真实缓存路径:
composer config --global cache-dir(Linux/macOS 默认~/.composer/cache,Windows 是%LOCALAPPDATA%\Composer\cache) - 把完整缓存目录(含
files/、repo/、archived/三个子目录)同步过去,不能只复制files/ - 运行
composer config --global cache-dir /path/to/restored/cache指向新位置 - 确认
$(composer config --global cache-dir)/repo/https---packagist.org/packages.json存在且非空(内容应为 Satis 生成的 JSON)
新增私有包时不能用 composer require,只能走 path 或 artifact
离线环境下 composer require 必然失败,因为它第一步就要联网查包名是否存在。唯一可行路径是把代码或 ZIP 当作本地源注册。
- 用
path类型:本地包目录下必须有合法composer.json(含name和version或dev-main),项目composer.json中添加:{"type":"path","url":"./packages/my-pkg"},再运行composer require vendor/name:dev-main - 用
artifact类型:所有 ZIP 必须按vendor-name/package-name-version.zip命名(如monolog/monolog-2.13.0.zip),放在同一目录下,执行composer config repositories.offline '{"type":"artifact","url":"/opt/artifacts/"}' - 两种方式都要求
COMPOSER_DISABLE_NETWORK=1环境变量已设,否则仍会尝试 fallback 到远程源
最易被忽略的一点:Satis 构建机和离线机的 PHP 版本(含小版本)、openssl 和 zlib 扩展必须一致。否则 ZIP 解压失败、SHA 校验跳过、甚至 autoload.php 加载时语法报错,这些都不会明确提示“PHP 版本不匹配”,只会表现为 Class not found 或 Segmentation fault。










