Azure Pipeline中Node进程锁定Prisma文件致二次部署失败
问题
环境信息:
- Node: 20.11.1
- Azure Pipeline: Ubuntu 22.04.4 LTS
- Prisma: 5.10.2
使用Azure Pipeline部署TypeScript编写的ExpressJS应用,首次部署正常,但二次部署时,部署后脚本中的npm run prisma-client(即prisma generate)报错:
Error: ENOENT: no such file or directory, copyfile '/home/site/wwwroot/node_modules/prisma/libquery_engine-debian-openssl-3.0.x.so.node' -> '/home/site/wwwroot/node_modules/.prisma/client/libquery_engine-debian-openssl-3.0.x.so.node'
原因是旧的应用进程(node js/index.js)正在占用libquery_engine-debian-openssl-3.0.x.so.node文件,导致无法复制替换。手动通过SSH杀死进程后部署可成功,但将杀进程命令加入部署后脚本时,脚本无权限访问目标进程。
解决方案
方案1:利用部署槽位的启停机制(推荐)
通过Azure CLI在部署槽位部署前先停止槽应用,避免文件被占用,部署完成后启动槽并交换到生产槽。修改Pipeline的Deploy阶段步骤:
steps: - task: AzureCLI@2 displayName: "停止预发布槽应用" inputs: azureSubscription: $(azureSubscription) scriptType: bash inlineScript: | az webapp stop --name $(webAppName) --slot $(slotName) --resource-group $(resourceGroupName) - task: AzureWebApp@1 displayName: "部署到预发布槽" inputs: azureSubscription: $(azureSubscription) appType: webAppLinux appName: $(webAppName) deployToSlotOrASE: true slotName: $(slotName) package: $(Pipeline.Workspace)/drop/$(Build.BuildId).zip startUpCommand: "npm run serve" - task: AzureCLI@2 displayName: "启动预发布槽并交换到生产槽" inputs: azureSubscription: $(azureSubscription) scriptType: bash inlineScript: | az webapp start --name $(webAppName) --slot $(slotName) --resource-group $(resourceGroupName) az webapp deployment slot swap --name $(webAppName) --resource-group $(resourceGroupName) --slot $(slotName) --target-slot production
方案2:将Prisma客户端生成到非node_modules目录
修改prisma/schema.prisma的生成路径:
generator client { provider = "prisma-client-js" output = "./../generated/prisma-client" // 自定义到项目内目录 }
调整代码中Prisma客户端的导入路径(例如从@prisma/client改为../generated/prisma-client,根据项目结构调整),这样生成的文件不在node_modules中,部署时不会被运行中的进程锁定。
方案3:将Prisma操作移到启动命令中
把prisma generate和migrate移到应用启动命令里,替换原startUpCommand:
npm run prisma-client && npm run migrate && npm run serve
同时删除部署后脚本中的npm run prisma-client和npm run migrate命令。Azure Web App启动新应用时会先停止旧进程,此时文件无占用,启动时执行生成和迁移操作(migrate deploy是幂等的,不会重复执行已应用的迁移)。
内容的提问来源于stack exchange,提问作者caleb-kwp
相关产品推荐
相关产品推荐

