composer本身不部署代码,仅管理依赖;所谓“自动化部署”是通过scripts字段串联git pull、rsync、php artisan migrate等命令,并严格控制执行时机、权限与远程上下文。

composer 本身不部署代码,它只装依赖;所谓“自动化部署”,是你用 scripts 字段把 git pull、rsync、php artisan migrate 这些命令串起来,并控制好执行时机、用户权限和远程上下文。直接写 "deploy": "rsync -avz ./ user@prod:/var/www/app" 看似简单,上线后大概率卡在权限拒绝、vendor 加载失败或数据库迁移交互提示上。
post-install-cmd 不会在生产服务器自动触发
很多人误以为在本地 composer install 后,post-install-cmd 也会在服务器上跑一遍——其实它只在你当前执行 composer install 的那台机器上运行,且默认是本地。如果你没显式 ssh 过去执行,它根本不会动。
- CI/CD 中执行
composer install --no-dev,脚本只在构建机运行,和目标服务器无关 -
post-install-cmd里调用php artisan config:cache会失败,因为 Web 用户(如www-data)没权限写storage/ - 真正该用的模式是:本地准备 → 推代码 → 远程登录执行 → 分阶段调用
composer run-script deploy:install等 - 若必须用钩子,优先选
post-autoload-dump(autoloader 生成后才执行),比post-install-cmd更可靠
rsync 同步时 vendor 目录必须排除
同步整个项目目录(含 vendor/)是常见但高危操作:传输慢、易中断、类加载路径错乱、权限继承混乱。生产环境应该让 composer install 在目标机上原地执行。
- 同步命令必须带
--exclude="vendor/" --exclude=".git" --exclude="node_modules/" -
rsync -avz --delete很危险:如果源目录临时缺失某个文件,目标会被清空;建议先用--dry-run验证 - 目标服务器需预装
composer和匹配的 PHP 版本;否则改用curl -sS https://getcomposer.org/installer | php下载composer.phar临时执行 - 远程执行时加
--no-dev --optimize-autoloader --classmap-authoritative,三者缺一不可
敏感操作必须加 --no-interaction 和 --force
像 php artisan migrate 或 php artisan storage:link 这类命令,默认会等待用户确认(Are you sure?)。一旦放进脚本,就会永久卡住,直到超时失败。
-
php artisan migrate --no-interaction --force是线上部署底线,漏掉--force在非本地环境默认不执行 -
php artisan config:clear前要确保storage/可写,否则报Permission denied;建议用chown -R www-data:www-data storage/显式修复 - 别在脚本里写
exec('composer install')—— 会递归触发自身,死锁 - 环境判断别硬编码,用
php -r "echo getenv('APP_ENV') ?: 'prod';"动态读取
自定义脚本名比生命周期钩子更可控
把所有逻辑塞进 post-install-cmd,会导致本地开发时也自动清缓存、跑迁移,容易误伤。不如定义明确用途的脚本名,按需手动触发。
- 在
composer.json里定义:"deploy:sync": "rsync -avz ..."、"deploy:activate": "ssh user@prod 'cd /path && php artisan config:cache'" - CI 中分步调用:
composer run deploy:sync && composer run deploy:activate,失败即停,定位快 - 复杂逻辑封装成 PHP 类(如
App\Deploy\Runner::onActivate),避免 shell 片段跨平台问题 - 所有路径用
${PWD}锚定,不依赖相对路径;所有 PHP 命令显式指定php解释器,不靠系统默认
rsync 或 ssh 命令里的用户、目录、PHP 路径,全都要提前验证可访问;哪怕只是少了一个 cd {{release_path}},composer install 就会报 No composer.json found。











