生产环境绝不能运行composer update,因其会修改composer.lock、重算依赖树、非原子写入vendor,导致类加载失败或服务中断;必须用composer install --no-dev --optimize-autoloader --no-interaction按锁定文件安装,并通过新旧目录隔离与原子链接切换实现零停机更新。

部署时不能直接运行 composer update,否则必然中断服务;零停机依赖更新的核心是“新旧环境隔离 + 原子切换”,不是靠 Composer 自身命令实现的。
为什么 composer update 不能用在生产部署中
它会修改 composer.lock、重新解析整个依赖图、下载新包并写入 vendor/,这个过程不可逆且非原子——期间 PHP 进程可能加载到一半新旧混杂的类,报 Class not found 或方法不存在错误。更严重的是,它会阻塞 Web 请求,因为文件写入和 autoloader 重建不是并发安全的。
-
composer update是开发阶段行为,用于生成新的composer.lock,不应出现在 CI/CD 或部署脚本里 - 生产部署必须用
composer install --no-dev --optimize-autoloader --no-interaction,严格按锁定文件安装 - 若依赖变更已合入主干,应先在本地或预发环境跑通
composer update,提交更新后的composer.lock,再走部署流程
零停机依赖更新的真实路径(以 Laravel Envoyer 为例)
真正起作用的不是 Composer,而是部署工具对目录结构和符号链接的控制。Composer 只负责在新目录里安静装好依赖,不碰正在运行的代码。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 每次部署拉取代码后,Envoyer 在
releases/20260921120000/这类时间戳目录中执行composer install - 所有构建操作(
npm run build、php artisan migrate)都在该独立目录完成 - 全部就绪后,仅用一条
ln -sf releases/20260921120000 current切换链接,毫秒级完成 - 旧
current指向的目录保留在磁盘上,可随时回滚,不影响新进程加载
Docker Compose 场景下如何避免依赖更新导致重启中断
容器内执行 composer install 本身不等于服务中断,但如果你把 vendor/ 直接挂载进容器,或者在运行中的容器里手动执行安装,就会触发问题。
- 正确做法:将
composer install写进Dockerfile的构建阶段,镜像里自带完整vendor/ - 禁止使用
volume挂载vendor/到宿主机——这会导致容器内外 autoload 冲突 - 如需热更新依赖(极少见),应重建镜像 +
docker compose up --detach --force-recreate,让新容器启动后再优雅停止旧容器 - 健康检查探针(
healthcheck)必须覆盖 autoloader 加载能力,例如curl -f http://localhost:8000/health返回 200 才认为新容器就绪
容易被忽略的关键点
很多人以为只要用了符号链接或容器就自动零停机,其实漏掉了两个硬性前提:
-
composer.lock必须提交到 Git,且每次依赖变更都由人审阅后合入,不能让 CI 自动执行composer update并提交 lock - 如果项目用了
opcache,PHP 进程可能缓存了旧vendor/中的类文件,必须配合opcache_reset()或重启 PHP-FPM 进程——但这和“零停机”冲突,所以推荐在新容器/新 release 目录里用全新 PHP 进程,而非复用旧进程

















