生产环境绝不能直接运行 composer install,必须在构建阶段完成依赖安装并整体同步代码包,否则将引发权限混乱、环境漂移和安全泄露三类硬伤;必须使用 --no-dev --optimize-autoloader --no-interaction 三参数组合,且 Nginx 需严格限制 .env、.lock、/vendor/ 等路径访问。

生产环境不能运行 composer install,必须在构建阶段完成依赖安装并整体同步代码包。这不是权衡项,而是避免 502、类找不到、权限错误和密钥泄露的硬性要求。
为什么生产机上绝对不能跑 composer install
看似省事,实则触发三类不可控问题:
-
file_put_contents(./composer.json): failed to open stream: Permission denied—— 不是 Composer 报错,是 web 用户(如www-data)对vendor/或composer.lock没写权限,排查耗时远超预估 - 环境漂移:
Your platform does not meet the requirements,比如本地 PHP 8.2,线上还是 8.1,platform-check直接中断部署 - 安全暴露:Nginx 配置稍有疏漏(如未禁用
.env),攻击者几秒就能下载到数据库密码、API 密钥
composer install 必须带的三个参数
它们不是“建议组合”,而是互锁生效的最小安全集,漏一个就可能让服务响应变慢、偶发 500 或 CI 卡住:
-
--no-dev:跳过require-dev中所有包(如phpunit、symfony/debug-bundle),否则会进autoload.php,拖慢类加载 + 暴露调试入口 -
--optimize-autoloader:生成vendor/composer/autoload_classmap.php,把类名直连文件路径,单次类加载从平均 1.2ms 降到 0.05ms;不加它,高并发下 autoload 就是 I/O 瓶颈 -
--no-interaction:防止遇到平台提示(如 “Do you want to store credentials for github.com?”)卡住 CI 流水线,Docker 构建时会直接超时失败
Nginx 必须显式禁止访问的路径
try_files $uri $uri/ /index.php?$query_string 只管路由转发,不拦文件下载。真正起作用的是 location 规则:
立即学习“PHP免费学习笔记(深入)”;
-
location ~ /\.(env|json|lock|git|hg|svn)$ { deny all; }:干掉所有带后缀的配置与元数据文件 -
location ^~ /vendor/ { return 403; }:用^~前缀匹配,确保比location ~ \.php$优先,彻底封死源码目录遍历 -
location = /composer.json { return 403; }:单独封死根目录下的关键文件(^~对=不生效,得用精确匹配)
PHP-FPM 权限和 opcache 的关键检查点
502 Bad Gateway 很多时候不是 Nginx 或网络问题,而是 PHP-FPM 进程读不到类文件:
- 确认
www.conf里的user和group(如www-data)对vendor/、storage/、bootstrap/cache/有读 + 执行权限(目录必须带+x才能进入) -
listen = /run/php/php8.1-fpm.sock的父目录/run/php/必须允许该用户写入;否则改用listen = 127.0.0.1:9000绕过 Unix socket 权限问题 - 确认
opcache.enable=1且opcache.validate_timestamps=0;部署后必须手动执行opcache_reset()或重启 PHP-FPM,否则旧字节码还在生效
最常被忽略的其实是构建与部署之间的“交接”:vendor/ 目录必须由构建机生成并完整同步,而不是靠 rsync 差量覆盖——哪怕只少一个 .php 文件,上线后就是 Class not found。这一步没有容错空间。



















