【Azure - App Service】如何使用PowerShell一键部署前端代码到微软Azure云的App Service上
前言
前段时间由于项目需求总结了Azure上的Local Git部署方式,但是也不是每个项目都适合这种方式。不同项目有自己的特点,需要使用不同的不是方式。好在Azure App Service 提供了多种内置的部署方式很App的运行方式。
这次要使用的就是使用压缩包的形式进行部署,代码是React前端项目。
使用Local Git方式部署失败
那至于为什么不使用Local Git部署方式 呢?主要还是这里面也有很多坑,之前使用的Local Git方式部署的是.net core的项目,可能是这东西是微软出的原因,App Service 对其支持特别好,只要把代码push上去,它就能自动的帮你编译和部署。
但是当我用同样的方式部署部署的时候总是失败,而且耗时很长。后来又通过.deployment 文件设置了自定义部署,但是仍然不行,各种出错。所以期待有高手过来指导一下。
Local Git部署-死。
使用FTP方式部署
在折腾了一圈Local Git方式部署失败之后,尝试转换下方向。把目标对准了FTP方式部署,为啥呢?因为之前发现在服务器上build+deploy没办法一气呵成,尤其是build的时候各种出错。即使解决了对应的错误,又出了内存不足的错误,所以相对来讲部署质量没办法控制。
而看到微软官方文档上有FTP部署的方式,那么是不是可以把build放到本地,然后直接把build好的文件直接上传到服务器呢?因为这样的话就能创建一个本地的脚本,每次部署的时候只需要运行一下这个脚本就行了,也省了不少事。
结果折腾了一圈下来还是有问题。
一开始使用PowerShell的module PSFTP来上传build好的文件,但是最后发现有部分文件能上传上去,有部分不能上传。然后使用FTP客户端又试了几遍,还是不行,FTP客户端显示部分文件被占用。手动停掉App Service之后,可以上传,估计是App Service在运行的时候把部分文件占用了的原因。
然后尝试在脚本中加入 az webapp start/az webapp stop 命令在上传的前后停止和启动App Service 但是还是没办法正常上传。
FTP部署-死。
使用ZIP方式部署
后来通过观察VSCode插件的部署,似乎每次部署都会生成zip文件再往Azure上发布。那我可不可以自己也是用这种方式来试试呢?然后查了一下微软的官方文档确实也支持zip方式部署。而且Azure Cli就有这个命令 az webapp deploy。
1. Azure Cli部署
命令非常简单,制定app service 对应的Resource Goup, App Name以及zip包的路径就行。
az webapp deploy --resource-group ResouceGroup --name AppName --src-path SourcePath
当然为了确保部署能够成功,最好在这个代码之前再加上一个。
az login
但是,但是。。。这个命令还是不成功啊。WTF...
试了n回,尝试了各种方法,Google也没找到对应的方法。希望有解决这个问题的大神分享一下。
az webapp deploy - 死。
2. Azure PowerShell部署
在查看微软官方文档的时候发现除了可以使用Azure Cli还可以使用Azure PowerShell,这当然是我熟悉的方式了。怀着试试也不会怀孕的想法,试了一下这个命令。
然后,病狗。成功了^_^。
这个命令跟Azure Cli的使用方式几乎一模一样也是3个参数,Resource Group, App Name, 压缩包路径。
Publish-AzWebApp -ResourceGroupName Default-Web-WestUS -Name MyApp -ArchivePath
在生成压缩包的时候要稍微注意一下,App Service会把解压后的东西直接放到wwwroot目录下,换句话说,压缩包的跟路径应该跟wwwroot目录是一致的。也是就说Zip包的跟路径就是你应用程序运行的跟路径,也是部署的跟路径。
整合编译部署的脚本
既然问题已经得到解决,那么接下来就是把它做成一个脚本,以后使用的时候就能更方便了。也不用依耐别人去部署了。废话不说上代码
1. 在App根目录下面新建build.ps1
2. 输入以下内容
[CmdletBinding()]param( # Parameter help description [Parameter(Mandatory)] [string] $ResourceGroup, [Parameter(Mandatory)] [string] $AppName, [switch] $Deploy, [switch] $Pull, [switch] $NoBuild, [switch] $Clear) if ([bool]$Clear) { if (test-path ".\build" -PathType:Container) { Write-Host "[$(Get-Date)] Clearing output..." -ForegroundColor:Cyan Remove-Item ".\build" -Recurse -Force -ErrorAction:Stop }}if ([bool]$Pull) { if ($null -eq (Get-Command git -ErrorAction SilentlyContinue)) { throw "Git client not installed or can't fined the git.exe tool." } Write-Host "[$(Get-Date)] Pull updates from remote repository." -ForegroundColor Cyan git pull}if (-not [bool]$NoBuild) { Write-Host "[$(Get-Date)] Build start..." -ForegroundColor:Cyan npm run build --prod Write-Host "[$(Get-Date)] Build complete" -ForegroundColor Cyan}if ([bool]$Deploy) { if (-not (Get-Module -ListAvailable -Name AZ )) { throw "Azure PowerShell module not installed. Please go to https://github.com/Azure/azure-powershell/releases install the AZ PowerShell" } if (-not (test-path -path "$pwd\temp" -PathType:Container)) { New-Item -Path "$pwd\temp" -ItemType:Directory | Out-Null } $archiveName = "$pwd\temp\$($AppName)_$((Get-Date).ToString("yyyyMMdd_HHmmss")).zip" Write-Host "[$(Get-Date)] Compress artifacts into ZIP file ..." -ForegroundColor:Cyan Compress-Archive -Path "$pwd\build\*" -DestinationPath $archiveName Write-Host "[$(Get-Date)] Created ZIP file at $archiveName" -ForegroundColor:Cyan $azContext = Get-AzContext -ErrorAction:SilentlyContinue if ($null -eq $azContext -or $null -eq $azContext.Account) { Write-Host "[$(Get-Date)] Login to Azure ..." -ForegroundColor:Cyan Connect-AzAccount Write-Host "[$(Get-Date)] Login success" -ForegroundColor:Cyan } Write-Host "[$(Get-Date)] Deploying to Azure App Service [$($AppName)]" -ForegroundColor:Cyan -NoNewline $deployjob = Publish-AzWebApp -ResourceGroupName $ResourceGroup -Name $AppName -ArchivePath $archiveName -Force -Confirm:$false -AsJob do { Write-Host "." -NoNewline -ForegroundColor:Cyan Start-Sleep -Seconds 1 } while ($deployjob.State -eq 'Running') Write-Host "Done" -ForegroundColor Green Receive-Job -Job $deployjob -AutoRemoveJob -Wait | Select-Object Name, ResourceGroup, Location, State | Format-Table Remove-Item -Path $archiveName -Force Write-Host "[$(Get-Date)] Removed ZIP file $archiveName" -ForegroundColor:Cyan Write-Host "[$(Get-Date)] Deploy complete" -ForegroundColor:Cyan}
这个脚本依赖于Azure PowerShell所以在使用之前需要先安装Azure PowerShell。
移步下面的链接来安装Azure PowerShell。
https://github.com/Azure/azure-powershell/releaseshttps://github.com/Azure/azure-powershell/releases
3. 脚本使用
build.ps1 [-ResourceGroup] [-AppName] [-Deploy] [-Pull] [-NoBuild] [-Clear] []
参数说明
-ResourceGroup 资源组名字
-AppName App Service 的名字
-Deploy 是否发布到Azure
-Pull 是否在build之前先拉取代码
-NoBuild 如果代码没有更新只是想重新部署,可以使用这个参数来节省时间
-Clear 是否清除build目录
使用举例:
先build再部署
.\build.ps1 -ResourceGroup <resource group name。 -AppName -Deploy
Pull, Build + Deploy
.\build.ps1 -ResourceGroup <resource group name。 -AppName -Deploy -Pull
只部署
.\build.ps1 -ResourceGroup <resource group name。 -AppName -Deploy -NoBUild
只build
.\build.ps1 -ResourceGroup <resource group name。 -AppName
Clear,Pull , Build + Deploy
.\build.ps1 -ResourceGroup <resource group name。 -AppName -Deploy -Clear -Pull
总结
本文总结了几个Azure部署方式的坑,以及如何使用Azure PowerShell来部署编译打包后的文件到Azure服务器上。最后分享了一下整合的PowerShell脚本。
Azure Cli和FTP部署失败的问题尚未解决,期待高手分享。