离线容器中直接装Composer失败,因apt install或curl安装脚本均需联网下载deb包或校验签名;正确做法是在联网机生成composer可执行文件,COPY进镜像并chmod+x,再断网运行composer install --no-plugins --no-scripts --no-autoloader验证。

离线容器里直接装 Composer 为什么总失败
因为 apt install composer 或 curl -sS https://getcomposer.org/installer | php 都会触发网络请求——前者拉 deb 包,后者校验签名并下载最新版 Phar。离线环境里这些操作必然卡在 DNS 解析或连接超时。
真正可行的路径只有一条:把 Composer 当作静态二进制文件 baked 进镜像,全程不执行任何联网逻辑。
- 在联网机器上用
php composer-setup.php --install-dir=/usr/local/bin --filename=composer生成可执行脚本(不是 Phar 封装) - Dockerfile 中用
COPY复制该文件,别用RUN curl | php - 必须加
RUN chmod +x /usr/local/bin/composer,否则容器内执行报Permission denied - 镜像启动后,
composer --version成功 ≠ 离线可用;要断网后跑composer install --no-plugins --no-scripts --no-autoloader才算过测
为什么光改 repo.packagist 不顶用
执行 composer config --global repo.packagist false 只禁了元数据入口,但 ZIP 包仍从原始 dist.url 下载——比如 https://github.com/monolog/monolog/releases/download/2.10.0/monolog-2.10.0.zip。局域网打不开 GitHub,国内公开镜像(阿里云、USTC)也不托管 ZIP 文件,只缓存 packages.json。
验证方式很简单:composer show monolog/monolog --verbose,看输出里的 dist.url 字段是不是还指向外网地址。
- 必须让所有依赖的 ZIP 都能通过内网 HTTP 直连 GET 到,比如
https://pkgs.internal/dist/monolog/monolog/2.10.0/xxx.zip - Satis 生成的
dist/目录得由 Nginx 精确暴露,root必须指向输出目录绝对路径 - Nginx 配置里必须加
types { application/json json; },否则返回text/plain,Composer 拒收 - 项目级
composer.json中的仓库 URL 必须以/结尾,写成"url": "https://pkgs.internal/",少斜杠会拼错路径
用 Satis 构建私有镜像时最常踩的三个坑
Satis 不是服务,只是静态文件生成器。它不监听端口、不自动更新、不处理权限——所有“失败”基本都源于配置与部署错位。
-
satis.json里"repositories"不能为空或写"*/*",Satis 不支持无限制抓取;得明确写包名通配,如"yiisoft/yii2-*" - 生成的
web/packages.json必须放在 Web 可 GET 路径下(如/var/www/satis/web),且访问路径就是https://pkgs.internal/packages.json,结尾不能多加/packages.json - 项目
composer.json中必须显式声明私有源:"repositories": [{"type": "composer", "url": "https://pkgs.internal/"}],同时设"packagist.org": false,否则 Composer 仍 fallback 到公网 - 若 build 报
Could not fetch https://api.github.com/...,检查是否开了 GitHub API 限流——加"github-protocols": ["https"],或设环境变量GITHUB_TOKEN
离线安装依赖时怎么绕开网络校验
就算镜像搭好了,composer install 还可能因残留配置去连外网。硬性开关必须全开:
- Dockerfile 中加
ENV COMPOSER_DISABLE_NETWORK=1——这是强制开关,不设它,--no-network参数无效 - 运行
RUN composer config --global repo.packagist false彻底关闭默认源 - 如果要用本地 mirror,用
RUN composer config --global repos.my-mirror composer file:///opt/mirror,路径必须是容器内真实存在的绝对路径 - 避免用
composer create-project,改用composer init+ 手动复制预构建的vendor/+composer dump-autoload -o
最容易被忽略的是:Satis 输出的 packages.json 时间戳若早于当前日期太多(比如显示“2026年10月15日”),说明镜像没更新,但 Composer 不会报错,只会静默 fallback——得人工核对时间戳和包数量。











