post-install-cmd 仅在 vendor 不存在/为空、composer.lock 缺失或不匹配、且未加 --no-scripts 时执行;ci 中因缓存常被跳过,应改用显式 run-script 部署。

CI/CD 里 composer install 总不执行 post-install-cmd?
不是脚本写错了,而是触发条件根本没满足。post-install-cmd 只在 vendor/ 不存在或为空、composer.lock 缺失或与 composer.json 不匹配、且没加 --no-scripts 时才跑。CI 流水线里常因缓存保留了旧 vendor/ 或 lock 文件完整,导致它静默跳过。
实操建议:
- 别依赖它“每次部署都跑”,把它当成“首次构建”专用钩子;真要每轮都执行的动作(如清缓存、设权限),定义成独立脚本名,比如
"scripts": { "deploy:setup": ["@php artisan cache:clear", "@php artisan config:clear"] } - CI 脚本里显式调用:
composer install --no-dev --optimize-autoloader && composer run-script deploy:setup - 确认 CI 环境没默认加
--no-scripts(某些托管平台如 GitLab CI 的 Composer 模板会自带)
生产环境部署必须加哪些参数?
--no-dev --optimize-autoloader 是基础,但漏掉 --no-scripts 或 --no-plugins 就可能在线上误执行开发期脚本,甚至被恶意包利用。
实操建议:
- 安全底线:所有生产部署命令必须带
composer install --no-dev --optimize-autoloader --no-scripts --no-plugins - 需要执行关键部署动作时,改用
composer run-script deploy:xxx --no-dev,可控、可审计 - CI 配置里把这串参数写死,别靠文档或人工记忆
- 如果项目真依赖某个钩子(比如前端资源构建),只保留那一个事件(如
post-update-cmd),并在脚本里加环境判断:if [ "$APP_ENV" = "prod" ]; then ... fi
Docker 构建时 vendor 缓存总失效?
根本原因是 COPY . /app 把整个项目目录一次性复制进去,只要任意文件变动(比如改一行 PHP),Docker 就丢弃前面所有 layer 缓存,重跑 composer install。
实操建议:
- 分层 COPY:
COPY composer.json composer.lock ./→RUN composer install --no-dev --optimize-autoloader→COPY . . - Alpine 镜像记得补依赖:
RUN apk add --no-cache curl unzip php82-openssl - 验证
composer.json是否真在容器内:RUN ls -l /app/composer.json,别假设路径对 - 多阶段构建时,用
COPY --from=builder /app/vendor /app/vendor,别在 final stage 重复 install
怎么让部署脚本跨平台又安全?
写 chmod 或 chown 命令在 Windows 上直接报错;裸写 artisan 在某些环境里找不到可执行文件;硬编码路径导致挂载后失效——这些都会让自动化脚本在不同环境崩掉。
实操建议:
- 所有命令加解释器前缀:
@php artisan cache:clear,不是artisan cache:clear - 避免 shell 内置命令,权限/文件操作封装进 PHP 脚本里(
php scripts/fix-perms.php),用file_exists()和chmod()更可靠 - 路径一律用
${PWD}/storage或__DIR__动态生成,别写../storage - 敏感操作(如写配置)前加校验:
if [ ! -f ".env" ]; then echo "Missing .env"; exit 1; fi











