I recently had the need to deploy an ASP.NET Core web project to an Azure Web App instance from a Linux build agent outside Visual Studio Team Services. As you expect, the world outside the Microsoft development stack is relatively more difficult to integrate, and documentation is still lacking on some of these aspects, unfortunately.
That’s when my Googling endeavor began. How can I deploy an ASP.NET Core build artifact from a Linux build agent outside VSTS — in my case, I was using GitLab — to an Azure Web App instance in an automated way? Using the integrated Deployment Options in the Azure Web App blade was not an option since I was building the app myself.
Fortunately, there’s this deployment management system called Kudu behind every Azure Web App that can be easily be accessed by following this URL: https://{your-webapp-name}.scm.azurewebsites.net. Kudu has a very interesting REST API that we’re going to leverage in order to upload our build artifact in a zipped format so that it automatically unzips and puts the content inside the wwwroot folder without too much of a hassle.
Building the app and zipping the output folder
My build script started with the usual ASP.NET Core build commands:
-
- Restore all the necessary NuGet packages for that project
dotnet restore
- Build the project in Release mode
dotnet build -c Release
- Publish the project to an output folder called out as a deployment artifact
dotnet publish -c Release -o out
- Zip the contents of that folder to a file called out.zip
cd out; zip -r ../out.zip *; cd ..
- Restore all the necessary NuGet packages for that project
Deploying the artifact to the Azure Web App instance using the Kudu Zip Deployment API endpoint – a.k.a The Tricky Part
By the name, it seems really complicated. But it’s really not. All it takes is a one-line command and you’re done. But before that, there’s some date we need to gather.
In order to communicate with your Kudu instance, you have to authenticate. Otherwise, anyone would be able to deploy to your website and that’s not cool. This is the part the documentation starts falling short. In order to see what username and password you should use, you have to download your Publish Profile from your Azure Web App blade:
With your publish profile in hands, look for the first <publishProfile> tag — the one that is named {your-website-name} – Web Deploy — and find the attributes called userName and userPWD. Get their values and keep them somewhere, you’re going to need them later.
With those in hand, open your deployment script and add the following line:
curl -X POST -u '{userName}':{userPWD} --data-binary @out.zip https://{your-webapp-name}.scm.azurewebsites.net/api/zipdeploy
Let’s understand this line a little further. We’re using curl to make an HTTP POST request to our Kudu instance REST API endpoint for the zip deployment system with a payload containing our build artifact from before.
- -u ‘{userName}’:{userPWD} – the -u means user, we’re authenticating the request with the username and password from our publish profile. Keep in mind your username might have a dollar sign ($) in it, therefore we have to put it inside a single quote so it’s not understood as an environment variable.
- –data-binary @out.zip – that’s our payload, the files zipped from the previous step during the build process. If you named your file differently, make sure you insert the right name here. Kudu then automatically unzips our files and places them inside the wwwroot folder.
- https://{your-webapp-name}.scm.azurewebsites.net/… – that’s your Kudu instance address. Replace the {your-webapp-name} part with your actual web app name.
Verifying your deployment
To check whether this really worked, navigate to your Kudu homepage — again {your-webapp-name}.scm.azurewebsites.net — click on Debug Console on your top navigation bar, then CMD. Navigate to site/wwwroot and check whether your build artifact files are there directly inside this folder.
They are? Cool. Head to {your-webapp-name}.azurewebsites.net and check whether your website successfully loads. Mine did:
Hi and thank you so much for this tutorial, it’s been really helpful as I need to deploy my Angular projects to Azure as well and was looking at a way to integrate just the deployment part and run my Continuous integration on Gitlab with all the tests and such.
That said, I have ran into a couple of problems. Being an Angular project I’m using a different docker image: https://hub.docker.com/r/weltn24/up-docker-node-chrome-headless/tags/ and I’m guessing because of it I’m getting an error saying “zip:command not found” even after I tried installing a zip package before running that command and I can see p7zip is successfully installed right before that command failing.
Also — have you configered Kudu to delete the existing files in the folder or it just knows how to do that by itself?
Thanks!
Hi Sebastian, glad to have helped! I’m afraid I can’t help you with the zip command problem, however regarding the behavior of Kudu’s Zip Deployment on the deletion of previous files, this is what the documentation says:
Here’s the link to the original source.