Menu

What you should know when deploying .NET 6 application to Linux based App Service?

I recently worked with .NET 6 application and from cost efficiency reasons I decided to deploy application to Linux based App Service. Everything didn't happen without problems so this blog post describes what you should know when deploying .NET 6 application to Linux based App Service in Azure.

Why to use Linux based App Service?

Nowadays Linux based App Service have pretty much same features like Windows but pricing is more attempting. Linux based App Service is 50% cheaper than Windows counterpart. Pricing at 11.11.2021:

Windows based App Service (Premium v3 Service Plan) 

undefined

Linux based App Service (Premium v3 Service Plan)

undefined

Notes about building Azure Infrastructure with Bicep

App Service Plan creation

I struggled some time with multiple provisioning errors after I noticed this blog post by Azure App Service team. You should determine reserved property to true to use Linux.

Quotation from App Service team blog:

Note that the kind property also shows up in App Service Plans (ASP). At this time, the value of this property for the ASP is meaningless and has no impact on your resource. For example, you can set kind to “Linux” for the ASP, but that won’t make your ASP a Linux ASP; the reserved property is what makes this distinction (if reserved= true, it’s a Linux ASP, otherwise it’s a Windows ASP).

Used Bicep code to create App Service Plan:

resource appServicePlan 'Microsoft.Web/serverfarms@2021-02-01' = {
  name: 'plan-myapplication'
  location: resourceGroup().location
  sku: {
    name: 'S1'
  }
  properties:{
    reserved: true
  }
  kind: ((appServicePlanPlatform == 'Linux') ? 'app,linux' : 'windows')
  tags:tags
}

App Service creation

When you're using Windows based App Service netFrameworkVersion property (Site configs) determines the runtime version like this:

undefined

Unfortunately same property don't work with Linux. Instead of netFrameworkVersion you have to use linuxFxVersion property. 

Used Bicep code to create App Service Plan:

resource appService 'Microsoft.Web/sites@2021-02-01' = {
  name: 'app-myapplication'
  location: resourceGroup().location
  identity: {
     type: 'SystemAssigned'
  }
  properties:{
    serverFarmId: appServicePlan.id
    reserved: true
    siteConfig:{
      alwaysOn: true
      ftpsState: 'Disabled'
      appSettings: appSettings
      linuxFxVersion: 'DOTNETCORE|6.0'
      http20Enabled: true
    }
    httpsOnly: true   
  }
  tags:tags
}

There are a few things what you should know about linuxFxVersion property values. List of available built-in runtime values for web app (Linux) can be retrieved with the following Azure CLI command:

az webapp list-runtimes --linux

Currently (11/2021) command returned the following values:

[
  "DOTNETCORE|2.1",
  "DOTNETCORE|3.1",
  "DOTNET|5.0",
  "DOTNET|6.0",
  "NODE|14-lts",
  "NODE|12-lts",
  "NODE|10-lts",
  "NODE|10.1",
  "NODE|10.6",
  "NODE|10.14",
  "JAVA|8-jre8",
  "JAVA|11-java11",
  "TOMCAT|8.5-jre8",
  "TOMCAT|9.0-jre8",
  "TOMCAT|8.5-java11",
  "TOMCAT|9.0-java11",
  "JBOSSEAP|7-java8",
  "JBOSSEAP|7.3-java8",
  "JBOSSEAP|7-java11",
  "JBOSSEAP|7.3-java11",
  "PHP|7.3",
  "PHP|7.4",
  "PYTHON|3.8",
  "PYTHON|3.7",
  "PYTHON|3.6",
  "RUBY|2.5",
  "RUBY|2.6"
]

But value DOTNET|6.0 is not working and after deployment Stack selection is empty.

undefined

Instead of DOTNET|6.0 you have to use DOTNETCORE|6.0 to get this working.

undefined

Notes about deploying application (YAML)

Set runtime argument value to linux-x64 in publish task like this:

    - task: DotNetCoreCLI@2
      displayName: Create application artifact
      inputs:
        command: publish
        projects:  '**/*.csproj'      
        arguments: '--configuration 'Release' --framework 'net6.0' -r 'linux-x64' --self-contained false --output $(Build.ArtifactStagingDirectory)'
        modifyOutputPath: false
        publishWebProjects: false
        zipAfterPublish: True  

YAML Deploy pipeline

Application is executed in Container so you have to manually set Startup Command to get application running. It took some time to figure this out.

undefined

You can use startUpCommand property to configure application start up in application deployment task:

         - task: AzureWebApp@1
            displayName: Deploy application
            inputs:
              appType: 'webAppLinux'
              azureSubscription: 'azure-dev'
              appName: 'app-myapplication'
              package: "$(System.ArtifactsDirectory)/application/*.zip"
              deploymentMethod: 'zipDeploy'
              startUpCommand: 'dotnet MyApplication.dll'

Application settings

When using Linux you have to change app setting key separator from colon (:) which is typically used in Windows platform to double underscore (__). Note! underscore separator should also work in Windows.

[
  {
    "name": "Idp__Authority",
    "value": "https://auth.server.fi",
    "slotSetting": false
  },
  {
    "name": "KeyVault__Uri",
    "value": "https://kv-myapplication.vault.azure.net/",
    "slotSetting": false
  } 
]

Comments