composer install --no-dev 是生产环境唯一安全选项,因跳过开发依赖可避免测试框架类加载冲突、减小体积并防止运行时错误。

为什么 composer install --no-dev 是生产环境唯一安全选项
跳过 --no-dev 会导致 phpunit、mockery、phpstan 等开发依赖被装进生产目录,不仅增大部署体积,更可能因自动加载冲突引发运行时错误——比如 Class Mockery\Adapter\Phpunit\MockeryTestCase not found 这类报错,实际是测试框架类被意外加载所致。
- 必须在部署前清空
vendor/目录,避免残留旧包干扰 -
composer.lock文件必须随代码一起提交,且确保与本地开发环境一致;否则install会降级或升级版本,破坏可重现性 - 禁止在生产机上执行
composer update—— 它会改写composer.lock,且无回滚机制
PHP 扩展缺失导致 composer install 卡死或报错
常见现象是卡在 Loading composer repositories with package information,或直接报 ext-zip not loaded、ext-openssl not loaded。这不是网络问题,而是 PHP CLI 模式下扩展未启用。
- 检查 CLI 使用的 php.ini:
php -i | grep "Loaded Configuration File" - 确认
extension=zip.so、extension=openssl.so、extension=mbstring.so在该 ini 文件中已取消注释 - 重启 PHP-FPM 或 Apache 后,需重新验证 CLI 是否生效:
php -m | grep -E 'zip|openssl|mbstring' - 某些发行版(如 Ubuntu)需单独安装扩展包,例如:
apt install php-zip php-xml php-mbstring
权限问题:为什么 vendor/ 目录常被写入失败
Web 服务器用户(如 www-data)和部署用户(如 deploy)身份不一致时,composer install 生成的文件可能无法被 PHP 进程读取,典型报错是 failed to open stream: Permission denied。
- 部署时用目标 Web 用户执行命令:
sudo -u www-data composer install --no-dev --optimize-autoloader - 或统一所有者:
chown -R www-data:www-data vendor/,但注意不要误改项目源码权限 -
--optimize-autoloader必须加,它生成静态映射表,避免生产环境每次请求都扫描文件,否则 autoload 性能下降明显 - 若用 Capistrano 或类似工具,确保
shared/中的vendor/不被软链覆盖,否则权限继承混乱
CI/CD 流水线里怎么安全复用 Composer 缓存
本地缓存(~/.composer/cache)不能直接拷贝到生产机,因为路径硬编码、平台差异(如 Windows vs Linux 的符号链接)会导致 vendor/ 内部损坏。
- CI 阶段用
composer install --no-dev --prefer-dist --no-progress,并缓存vendor/目录本身(非 ~/.composer/cache) - 生产部署阶段禁用远程下载:
composer install --no-dev --no-progress --prefer-dist --ignore-platform-reqs,仅当确认 PHP 版本兼容时才加--ignore-platform-reqs - 若使用 Docker,把
composer install放进构建层,而非运行时;镜像内不保留composer二进制,减小攻击面
最常被忽略的是 autoload_files 和 classmap 的生成时机——它们只在 install 或 dump-autoload 时更新,如果手动修改了 composer.json 但没重跑 install,新注册的全局函数或 classmap 就不会生效,而错误日志里往往只显示 “function not found”,看不出根源。










