- Create an AppService Plan / Azure Web App
- Create and deploy an ASP.NET Core Web App to Azure
- Create and configure WebApp slots
- Use slots to deploy new versions of your web application with near-zero downtime
To create an Azure Web App, go to the Azure Portal and click on "Create a resource", in the next view choose "Web App".
When you reached the "Create Web App" wizard, follow the steps below:
- Choose the correct subscription
- Create a new resource group, name it "myFirstWebApps-rg"
- Under instance details, enter a name for your Web App (be careful: this must be a global unique name!)
- Publish: Code
- Runtime: .NET Core 3.0 Current
- Operation System: Windows
- Region: West Europe
- SKU and Size: S1
- To get familiar with other sizes, click "Change size"
Click "Next: Monitoring".
- Enable AppInsights
- Create a new AppInsights instance for it
When done, proceed to the "Review + create" screen.
Again, check that all the properties are filled with the expected values and click "Create".
When the deployment has finished, got to the resource and get familiar with all the configuration options discussed in the introduction talk.
Open the web app in your browser.
If you have created the web application already with option 1, go to the portal and delete the resource group - including all the newly created resources (you have to wait until it has finished, before proceeding). We will be creating the exact same resources now with the Azure CLI.
First, let's create the resource group.
BTW: You can check the results of each command in the Portal.
$ az group create --name myFirstWebApps-rg --location westeurope
{
"id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myFirstWebApps-rg",
"location": "westeurope",
"managedBy": null,
"name": "myFirstWebApps-rg",
"properties": {
"provisioningState": "Succeeded"
},
"tags": null,
"type": "Microsoft.Resources/resourceGroups"
}
Next, add an App Service Plan.
$ az appservice plan create -g myFirstWebApps-rg -n myFirstWebAppsPlan --sku S1
{
"freeOfferExpirationTime": null,
"geoRegion": "West Europe",
"hostingEnvironmentProfile": null,
"hyperV": false,
"id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myFirstWebApps-rg/providers/Microsoft.Web/serverfarms/myFirstWebAppsPlan",
"isSpot": false,
"isXenon": false,
"kind": "app",
"location": "West Europe",
"maximumElasticWorkerCount": 1,
"maximumNumberOfWorkers": 10,
"name": "myFirstWebAppsPlan",
"numberOfSites": 0,
"perSiteScaling": false,
"provisioningState": "Succeeded",
"reserved": false,
"resourceGroup": "myFirstWebApps-rg",
"sku": {
"capabilities": null,
"capacity": 1,
"family": "S",
"locations": null,
"name": "S1",
"size": "S1",
"skuCapacity": null,
"tier": "Standard"
},
"spotExpirationTime": null,
"status": "Ready",
"subscription": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"tags": null,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0,
"type": "Microsoft.Web/serverfarms",
"workerTierName": null
}
When the App Service Plan has been created, we can now add the Web App.
$ az webapp create -g myFirstWebApps-rg -p myFirstWebAppsPlan -n myFirstWebAppDevCollege
{
"availabilityState": "Normal",
"clientAffinityEnabled": true,
"clientCertEnabled": false,
"clientCertExclusionPaths": null,
"cloningInfo": null,
"containerSize": 0,
"dailyMemoryTimeQuota": 0,
"defaultHostName": "myfirstwebappdevcollege.azurewebsites.net",
"enabled": true,
"enabledHostNames": [
"myfirstwebappdevcollege.azurewebsites.net",
"myfirstwebappdevcollege.scm.azurewebsites.net"
],
"ftpPublishingUrl": "ftp://waws-prod-am2-217.ftp.azurewebsites.windows.net/site/wwwroot",
"geoDistributions": null,
"hostNameSslStates": [
{
"hostType": "Standard",
"ipBasedSslResult": null,
"ipBasedSslState": "NotConfigured",
"name": "myfirstwebappdevcollege.azurewebsites.net",
"sslState": "Disabled",
"thumbprint": null,
"toUpdate": null,
"toUpdateIpBasedSsl": null,
"virtualIp": null
},
{
"hostType": "Repository",
"ipBasedSslResult": null,
"ipBasedSslState": "NotConfigured",
"name": "myfirstwebappdevcollege.scm.azurewebsites.net",
"sslState": "Disabled",
"thumbprint": null,
"toUpdate": null,
"toUpdateIpBasedSsl": null,
"virtualIp": null
}
],
"hostNames": [
"myfirstwebappdevcollege.azurewebsites.net"
],
"hostNamesDisabled": false,
"hostingEnvironmentProfile": null,
"httpsOnly": false,
"hyperV": false,
"id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myFirstWebApps-rg/providers/Microsoft.Web/sites/myFirstWebAppDevCollege",
"identity": null,
"inProgressOperationId": null,
"isDefaultContainer": null,
"isXenon": false,
"kind": "app",
"lastModifiedTimeUtc": "2020-01-13T13:17:15.623333",
"location": "West Europe",
"maxNumberOfWorkers": null,
"name": "myFirstWebAppDevCollege",
"outboundIpAddresses": "137.117.218.101,137.117.210.101,137.117.214.210,137.117.214.88,137.117.212.13",
"possibleOutboundIpAddresses": "137.117.218.101,137.117.210.101,137.117.214.210,137.117.214.88,137.117.212.13,137.117.208.108,137.117.208.41,137.117.211.152",
"redundancyMode": "None",
"repositorySiteName": "myFirstWebAppDevCollege",
"reserved": false,
"resourceGroup": "myFirstWebApps-rg",
"scmSiteAlsoStopped": false,
"serverFarmId": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myFirstWebApps-rg/providers/Microsoft.Web/serverfarms/myFirstWebAppsPlan",
"siteConfig": null,
"slotSwapStatus": null,
"state": "Running",
"suspendedTill": null,
"tags": null,
"targetSwapSlot": null,
"trafficManagerHostNames": null,
"type": "Microsoft.Web/sites",
"usageState": "Normal"
}
The last step we need to have the same environment like when we created everything via the portal, is to add Application Insights.
The Azure CLI Application Insights component is still in preview. To access it, you first need to run:
$ az extension add -n application-insights
The installed extension 'application-insights' is in preview.
Now, let's create the AppInsights component for our application.
$ az monitor app-insights component create --app myFirstWebAppsAppIn --location westeurope --kind web -g myFirstWebApps-rg --application-type web
{
"appId": "14f1a266-629c-44aa-ad0f-9e09bed00f71",
"applicationId": "myFirstWebAppsAppIn",
"applicationType": "web",
"creationDate": "2020-01-13T06:23:58.761173+00:00",
"etag": "\"0500a71d-0000-0200-0000-5e1c0cfe0000\"",
"flowType": "Bluefield",
"hockeyAppId": null,
"hockeyAppToken": null,
"id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myFirstWebApps-rg/providers/microsoft.insights/components/myFirstWebAppsAppIn",
"instrumentationKey": "8bfd7511-d6ad-4ea8-9a10-d0db786ec415",
"kind": "web",
"location": "westeurope",
"name": "myFirstWebAppsAppIn",
"provisioningState": "Succeeded",
"requestSource": "rest",
"resourceGroup": "myFirstWebApps-rg",
"samplingPercentage": null,
"tags": {},
"tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"type": "microsoft.insights/components"
}
Add the Application Insights instrumentation key to your WebApp. Therefore, use the instrumentation key from the above output in the next command.
$ az webapp config appsettings set --settings APPINSIGHTS_INSTRUMENTATIONKEY=<YOUR_INSTRUMENTATION_KEY> -n myFirstWebAppDevCollege -g myFirstWebApps-rg
Now, we are all set to add a sample application.
We will use a .NET Core MVC application to demonstrate the deployment process to an Azure Web App. So first, let's create a demo application.
Create a local folder called devcollege and open it in the comannd line. CD into that folder and execute:
$ dotnet new mvc -o myFirstCoreApp
The template "ASP.NET Core Web App (Model-View-Controller)" was created successfully.
This template contains technologies from parties other than Microsoft, see https://aka.ms/aspnetcore/3.0-third-party-notices for details.
Processing post-creation actions...
Running 'dotnet restore' on myFirstCoreApp/myFirstCoreApp.csproj...
Restore completed in 60.34 ms for /Users/christiandennig/dev/myFirstCoreApp/myFirstCoreApp.csproj.
Restore succeeded.
After the wizard has finished, cd into the new folder myFirstCoreApp and open it in VS Code:
$ code .
Get familiar with the environment and have a look at the controller HomeController.
Set a breakpoint (F9) on method public IActionResult Index() in Controllers/HomeController.cs
Press F5 - if VS Code asks you about the environment, choose .NET Core
The project will now be built and after that, your browser will point to https:/localhost:5001.
Here is a workaround, if port 5001 is blocked on your machine.
Open file launch.json in the folder .vscode and add the env variable ASPNETCORE_URLS with a value that works for you.
Example:
When the breakpoint gets hit, get familiar with the tools of the debugger.
Open Views/Home/Index.cshtml and change the welcome text to "Welcome to the Azure Developer College".
Run it again locally and check, if the changes appear.
Now let's deploy the webapp to Azure.
If you haven't done so far, add the Azure App Service Extension (see: Challenge 0 - Setup your system)
Find your webapp in the extension and right-click --> Deploy to Web App...
If you can't find your subscription, press F1 and choose the Task Azure: Sign In.
After a few seconds the browser will show you your first web app running in Azure.
Open your web app in the portal and go to "Deployment Slots".
Create a new slot called "Staging" (choose clone settings from your production slot).
When finished, go back to VS Code.
Open Views/Home/Index.cshtml again and change the welcome text to "Welcome to the Azure Developer College - this time with slots!".
Check that your local development environment works as expected.
To deploy the application to the Staging slot, find your webapp in the Azure AppService extension, drill down to Deployment Slots and right-click --> Deploy to Slot...
Your current application will now be deployed to your "Staging" slot.
To see your staging slot in action, go to the slot in the portal and copy the URL in the overview blade.
Open your browser, navigate to the URL and check, if the headline contains the new text.
Also check the production slot (URL without "-staging").
Now that everything works as expected, go back to "Deployment Slots" and click on "Swap" (selecting the staging slot as source).
With this command, we are swapping the current "poduction" slot with our "Staging" slot...which basically means that the Load Balancer in front of our Web App points to "Staging" and promotes it as the new "production" slot.
Now check, that the production slot serves the new version of the website.
Optional: Split traffic 50:50 to staging and production a see what happens when you reload your page in the browser pointing to the production slot. What do you think, why does this happen??
Remove the sample resource group.
$ az group delete -n myFirstWebApps-rg