PROBLEM
Typically, when using ZipDeploy to push a WAR file (ex: my-app.war) to an Azure instance, we need to:-
- Rename my-app.war to ROOT.war.
- Place ROOT.war under webapps/.
- Zip up webapps/.
- Use ZipDeploy to push the zip file to an Azure instance.
This zip file will automatically be unzipped under site/wwwroot:-
D:\home\site\wwwroot
└── webapps
└── ROOT.war
Tomcat detects ROOT.war and will try to unpack the WAR file under ROOT/:-
D:\home\site\wwwroot
└── webapps
├── ROOT
│ ├── META-INF
│ │ └── ...
│ └── WEB-INF
│ └── ...
└── ROOT.war
The problem is sometimes Tomcat is unable to fully unpack ROOT.war because some files may be locked by some running processes. As a result, the web page fails to load and shows 404 error.
SOLUTION
A better and more stable solution is to use WarDeploy to push WAR file to an Azure instance because:-
- It simplifies the deployment process because we don’t need to create a zip file with webapps/ containing a WAR file named ROOT.war.
- Instead of relying on Tomcat to unpack the WAR file, WarDeploy will do the unpacking step elsewhere before copying to site/wwwroot/webapps/.
To use WarDeploy, you can use curl command or PowerShell script to do so.
Here’s an example of the PowerShell script:-
Param(
[string]$filePath,
[string]$apiUrl,
[string]$username,
[string]$password
)
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username, $password)))
Invoke-RestMethod -Uri $apiUrl -Headers @{ Authorization = ("Basic {0}" -f $base64AuthInfo) } -Method POST -InFile $filePath -ContentType "multipart/form-data"
If the PowerShell script above is called deploy.ps1, to push my-app.war to my-app Azure instance:-
deploy.ps1 -filePath D:\my-app.war -apiUrl https://my-app.scm.azurewebsites.net/api/wardeploy -username [USER] -password [PASSWORD]
Depending on the size of the WAR file, you may get “The operation has timed out” error after 100 seconds:-
Invoke-RestMethod : The operation has timed out
At D:\agent\_work\2ea6e947a\my-app\deploy.ps1:18 char:1
+ Invoke-RestMethod -Uri $apiUrl -Headers @{Authorization=("Basic {0}" ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
This will most likely to occur if the WAR file is too big (80MB+).
To fix this, increase the time out duration by adding -TimeoutSec option to Invoke-RestMethod statement:-
Invoke-RestMethod [OTHER_OPTIONS...] -TimeoutSec 300
Leave a Reply