用 satis + docker 最省事,5 分钟可跑通私有 composer 仓库,无需配置 web 服务器、php 环境或 git 权限;docker 镜像预装 php 8.2+、git、zip 等依赖,非 root 运行,规避本地环境问题;三步即可完成构建与验证:写 satis.json、docker run 构建、python 起服务;项目中需禁用 packagist.org 并显式声明 composer 类型仓库 url;satis 为静态生成工具,无自动更新能力,需手动或通过 ci 触发重建。

直接用 Satis + Docker 最省事,5 分钟能跑通,不需要配 Web 服务器、不用装 PHP 环境、也不用碰 Git 权限。
为什么别从源码或 Composer create-project 开始
新手常卡在 composer install 阶段:PHP 版本不匹配、ext-zip 缺失、bin/satis 权限报错,甚至 git clone 失败却只看到“Could not parse version”这种误导性错误。Docker 镜像已预装好所有依赖(PHP 8.2+、git、zip、curl),且以非 root 用户运行,避开了 90% 的本地环境问题。
- 镜像自带最新稳定版 Satis(dev-main 分支),支持 GitHub/GitLab 私有地址、
require-all和archive配置 - 无需提前配置 SSH key 或
git config --global credential.helper - 构建输出直接落在宿主机目录,可立刻用 Python HTTP 服务临时托管验证
三步跑通最小可用仓库
假设你有一个私有 GitLab 包 https://gitlab.example.com/team/utils,它根目录下有合法的 composer.json(含 "name": "team/utils"):
- 写
satis.json(注意homepage必须是最终访问 URL,哪怕只是本地测试):{ "name": "Team Internal", "homepage": "http://localhost:8000", "repositories": [ {"type": "vcs", "url": "https://gitlab.example.com/team/utils"} ], "require-all": true } - 执行构建:
docker run --rm -it -v $(pwd):/build -v $(pwd)/web:/output composer/satis build /build/satis.json /output - 启动临时服务验证:
cd web && python3 -m http.server 8000,然后访问http://localhost:8000/packages.json确认返回 JSON 且含packages字段
项目里怎么让 composer install 真正走你的仓库
这是最常被跳过的一步——即使 Satis 构建成功,composer install 默认仍会 fallback 到 packagist.org,导致包“明明存在却找不到”。关键就两行配置:
- 在项目
composer.json的根级加:"packagist.org": false -
repositories数组里必须用{"type": "composer", "url": "http://localhost:8000/"}(注意末尾斜杠不能少) - 删掉任何其他
repositories条目,避免干扰;require中的包名必须和私有包composer.json里的name完全一致(包括大小写)
验证命令:composer show team/utils 应直接输出包信息,而非报错 Package team/utils not found。
后续维护最容易忽略的点
Satis 不是服务,它不监听请求、不自动更新、不处理认证。每次 Git 仓库有新 Tag 或分支,都得手动重跑 docker run ... build。建议把构建命令写成一行脚本,配合 git pull 放进 CI 流水线;如果团队开始用 Artifactory 或 Nexus,记得它们需要显式启用 composer 协议类型,Generic 类型仓库对 Composer 无效。











