点击上方蓝字关注“汪宇杰博客”
最近我遭遇了一个奇怪的问题。使用Azure DevOps配置CI/CD管线,自动部署到Azure App Service以后,.NET Core的网站竟然会启动失败。我们来看看如何解决这个问题。
查找问题
首先,幸好,这是个staging环境。爆了以后,我发现网站竟然没有log,连log的目录都找不到,这非常奇怪。于是我决定在Azure启用开发模式,让网站输出详细错误信息。熟悉经典ASP.NET的同学可能知道,只要在web.config里设置个customError就行了。但是.NET Core没有这个东西,怎么办呢?我教大家一个猥琐小技巧:
.NET Core的设置,是优先用环境变量覆盖的。所以我们可以利用这点,在Azure App Service的设置里加这么一个环境变量:
ASPNETCORE_ENVIRONMENT:Development
更改设置的地方在Application settings页面
朋友们可能会问:我怎么知道这个值的?其实这个设置来源于Visual Studio
打开开发模式以后,输出了宇宙大爆炸的详细信息:
发现执行的代码路径竟然不是在App Service应有的网站根目录!于是我的代码找不到依赖项,就爆了。
怎么回事
我尝试了手动从VS部署,也是爆的。在Azure DevOps重新部署,也是爆的。甚至停用CD管线,用kudu直接build git的代码,也是爆的!我陷入了循环懵逼:
最终我删除并重建了一个新的App Service实例,用VS发布,居然就好了。但是我再次用CI/CD管线部署以后,又产生了大爆炸。细心的我,保留了网站运行正常时候的配置信息,与爆炸以后的配置对比发现,是多了这么一个设置:
这是个啥玩意儿
我追溯到一个微软Azure的announcement:https://github.com/Azure/app-service-announcements/issues/84
发现它是针对Azure Function设计的,这是App Service进一步包装以后的服务。与传统部署的差别就是,传统部署会把新文件覆盖到wwwroot目录,也就是我们的网站根目录,而用了RUN_FROM_PACKAGE的话,网站执行的时候会指向一个zip文件,压缩包的内容会映射到wwwroot目录,但会变成只读。
使用这个功能有一些好处,比如可预测、更快速的部署、更快速的启动性等等,具体大家可以去看微软公告的介绍。
恢复网站运行
想要临时恢复网站运行,非常简单,只要将WEBSITE_RUN_FROM_PACKAGE这个设置整个删除,重启网站,就可以恢复到部署前的良好版本。但是Azure DevOps将来的部署,将不会起作用。因为真实的wwwroot目录不会被更新了。
恢复至CD部署前版本:6980
那如何自动部署呢
我们需要修改Azure DevOps部署任务的默认值
编辑你的Release定义,在Tasks下找到Deploy Azure App Service子任务。
展开Additional Deployment Options,勾选 Select deployment method,然后手工选择为 Web Deploy,保存设置。
然后重新提交一个Release,等待成功部署。完成之后就可以看到正确的新版本被部署在wwwroot物理路径下了,网站也能正常启动: