
CI/CD中执行composer install前必须设COMPOSER_MEMORY_LIMIT
默认情况下,Composer在内存受限的CI环境(如GitHub Actions默认7GB、GitLab Shared Runner常为4GB)容易因OOM被kill,报错类似Killed或PHP Fatal error: Allowed memory size exhausted。这不是PHP配置问题,而是Composer自身加载依赖图时的峰值内存占用高。
实操建议:
- 在CI脚本开头统一设置:
export COMPOSER_MEMORY_LIMIT=-1(禁用限制)或export COMPOSER_MEMORY_LIMIT=2G(显式指定) - 不要依赖
php -d memory_limit=-1 composer install——部分CI镜像中PHP CLI的memory_limit对Composer进程不生效 - 若用Docker,确保基础镜像PHP配置未硬编码限制(检查
php -i | grep memory_limit)
为什么composer install --no-dev不能省略?
CI构建产物(如打包成phar、生成部署包、构建Docker镜像)应只含运行时依赖。--no-dev不只是提速,更是安全边界:dev依赖里的工具(如phpunit、infection)可能引入未审计的远程调用、调试后门或过时漏洞。
常见错误场景:
- 本地
composer.json里require-dev包含symfony/var-dumper,上线后意外暴露dump()调用导致敏感数据泄露 - CI误用
composer update而非install,导致composer.lock被意外修改,破坏可重现性 - 未加
--optimize-autoloader和--classmap-authoritative,导致生产环境autoload慢30%+(尤其Laravel/Symfony项目)
私有包拉取失败?关键在auth.json注入方式
CI环境无法交互输入GitHub/GitLab Token,必须预置凭证。但直接提交auth.json到仓库是严重安全风险。
正确做法:
- GitHub Actions:用
composer config http-basic.github.com ${{ secrets.GITHUB_TOKEN }} x-oauth-basic动态写入 - GitLab CI:通过
before_scriptecho生成auth.json,内容为{"http-basic": {"gitlab.example.com": {"username": "$CI_DEPLOY_USER", "password": "$CI_DEPLOY_PASSWORD"}}} - 绝对避免:
cp .ci/auth.json ~/.composer/auth.json——路径不可靠,且可能覆盖全局配置 - 验证是否生效:
composer show vendor/private-package应在CI日志中返回包信息,而非Could not find package
Docker构建中composer install应分层缓存
把composer install放在Dockerfile末尾会导致每次代码变更都重装全部依赖,CI耗时暴增。必须利用Docker layer cache机制拆分步骤。
典型高效写法:
COPY composer.json composer.lock ./ RUN composer install --no-dev --optimize-autoloader --classmap-authoritative COPY . .
注意点:
- 务必
COPY两个文件(composer.json和composer.lock),缺一不可;仅拷composer.json会导致Docker缓存失效(因lock文件变化不触发重建) - 不要用
ADD代替COPY——ADD会解压tar包,干扰缓存判断 - 若项目含平台配置(如
"platform": {"php": "8.1"}),需在RUN前用FROM指定对应PHP版本镜像,否则install会跳过兼容检查
composer install前不检查composer.lock是否与composer.json同步,导致开发提交了新依赖却没更新lock,CI静默使用旧版本——建议在CI第一步加composer validate --strict并设为失败退出。










