在群晖NAS上搭建Composer私有仓库必须用Docker运行Satis生成静态文件,再通过WebStation反向代理暴露HTTPS服务;不能直接在DSM终端运行,因PHP CLI环境不兼容、无Satis可执行文件且WebStation无法原生托管Satis仓库目录。

在群晖 NAS 上搭 Composer 私有仓库,不能只配 repositories 就完事——Satis 服务本身得跑在能被项目访问的 HTTP 环境里,而群晖默认没有 Web 服务器能直接托管 Satis 的 public/ 目录;更关键的是,Satis 构建过程依赖 PHP CLI 环境(含 ext-curl、ext-json、phar.readonly = Off),但群晖 DSM 的 PHP 套件不暴露 CLI 路径,也不允许改系统 php.ini。真能落地的路径只有一条:用 Docker 容器跑 Satis,再通过 WebStation 反向代理暴露出去。
为什么不能在 DSM SSH 里直接跑 Satis
Satis 是个 PHP 命令行工具,构建仓库需要完整执行:php bin/satis build satis.json web/。但在群晖 DSM 终端里:
- 系统自带的
php命令指向旧版(如 PHP 5.6),不支持 Satis 所需的ext-json或ext-curl - WebStation 绑定的 PHP(如
/volume1/@appstore/PHP82/usr/bin/php)虽可用,但它不提供bin/satis可执行文件,也未预装 Satis - 手动用
composer create-project composer/satis安装会失败:DSM 的 PHP CLI 缺allow_url_fopen、phar.readonly = On、CA 证书路径不对,连 GitHub ZIP 都拉不下来 - 即使硬凑出可运行环境,构建出的
web/目录也没法直接被 WebStation 当静态站托管——它需要真实 HTTP 服务响应packages.json请求,而非仅放一堆 JSON 文件
用 Docker 运行 Satis 并挂载到 WebStation
这是目前唯一稳定可行的方式。核心是让容器生成仓库文件,再由 WebStation 作为反向代理或静态文件服务对外提供 https://your-nas/satis/ 接口:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 拉取带 Satis 的镜像:
docker pull composer/satis:latest(官方镜像已内置 Satis,无需自己装) - 准备宿主机目录结构:
/volume1/docker/satis/ ├── satis.json ├── packages/ └── web/
其中satis.json写好你的私有包源(如 GitLab 地址)、packages/存放 Git 仓库克隆副本(确保群晖能git clone)、web/为空目录,用于接收构建输出 - 一次性构建:
docker run --rm -v /volume1/docker/satis:/build -w /build composer/satis:latest build satis.json web/。构建成功后,/volume1/docker/satis/web/下会出现packages.json和dist/等标准 Composer 仓库文件 - 在 WebStation 中新建一个站点,根目录设为
/volume1/docker/satis/web,绑定域名或端口(如satis.yourdomain.com或:8081),并确保启用 HTTPS(否则项目中"secure-http": true会拒绝访问)
项目中怎么正确引用这个私有源
别只改 composer.json 里的 repositories,还得处理几个实际卡点:
-
repositories的url必须是完整 HTTPS 地址,且证书有效。例如:"url": "https://satis.yourdomain.com",不能写http://或内网 IP(如http://192.168.1.100:8081),否则composer install会报Could not parse version constraint或静默跳过 - 如果用的是自签名证书,必须在项目所在环境(比如另一个 Docker 容器)里配置 CA 信任,或临时加
"secure-http": false(仅限测试) - 私有包的
composer.json中name字段必须全局唯一,且与你在satis.json的require项完全一致,例如:"require": {"myorg/mypackage": "dev-main"},对应包里"name": "myorg/mypackage" - 每次更新私有包代码后,必须重新运行上面的
docker run ... build命令,并清空项目本地缓存:composer clear-cache,否则 Composer 仍读旧的packages.json元数据
WebStation 反向代理比直接托管更可靠
如果你的私有仓库要供多个项目或外部 CI 使用,别把 web/ 目录直接设为 WebStation 站点根目录——它无法处理 Satis 的动态重写规则(如 /p/<package>.json</package> 路由)。更稳的做法是:
- 在 WebStation → 反向代理规则中新增一条:
来源 URL:/satis/,目标 URL:http://127.0.0.1:8082/ - 再起一个轻量容器专门跑 Satis HTTP 服务:
docker run -d -p 127.0.0.1:8082:80 -v /volume1/docker/satis/web:/usr/share/nginx/html nginx:alpine - 这样所有对
https://your-nas/satis/packages.json的请求都会被转发到容器内的 Nginx,完全兼容 Composer 客户端的协议要求
真正容易被忽略的是:Satis 构建时不会自动拉取私有 Git 仓库的最新 commit,除非你在 satis.json 里显式配置 "no-api": false 并确保群晖能访问 Git 服务(SSH key 或 token 需提前配进容器)。否则你看到的永远是第一次构建时的快照。

















