Build an ASP.NET Core and SQL Database app in Azure App Service on Linux


This article deploys an app to App Service on Linux. To deploy to App Service on Windows, see Build a .NET Core and SQL Database app in Azure App Service.

App Service on Linux provides a highly scalable, self-patching web hosting service using the Linux operating system. This tutorial shows how to create a .NET Core app and connect it to a SQL Database. When you're done, you'll have a .NET Core MVC app running in App Service on Linux.

app running in App Service on Linux

In this tutorial, you learn how to:

  • Create a SQL Database in Azure
  • Connect a .NET Core app to SQL Database
  • Deploy the app to Azure
  • Update the data model and redeploy the app
  • Stream diagnostic logs from Azure
  • Manage the app in the Azure portal

If you don't have an Azure subscription, create a free account before you begin.


To complete this tutorial:

Create local .NET Core app

In this step, you set up the local .NET Core project.

Clone the sample application

In the terminal window, cd to a working directory.

Run the following commands to clone the sample repository and change to its root.

git clone
cd dotnetcore-sqldb-tutorial

The sample project contains a basic CRUD (create-read-update-delete) app using Entity Framework Core.

Run the application

Run the following commands to install the required packages, run database migrations, and start the application.

dotnet restore
dotnet ef database update
dotnet run

Navigate to http://localhost:5000 in a browser. Select the Create New link and create a couple to-do items.

connects successfully to SQL Database

To stop .NET Core at any time, press Ctrl+C in the terminal.

Open Azure Cloud Shell

Azure Cloud Shell is an interactive shell environment hosted in Azure and used through your browse. Azure Cloud Shell allows you to use either bash or PowerShell shells to run a variety of tools to work with Azure services. Azure Cloud Shell comes pre-installed with the commands to allow you to run the content of this article without having to install anything on your local environment.

To run any code contained in this article on Azure Cloud Shell, open a Cloud Shell session, use the Copy button on a code block to copy the code, and paste it into the Cloud Shell session with Ctrl+Shift+V on Windows and Linux, or Cmd+Shift+V on macOS. Pasted text is not automatically executed, so press Enter to run code.

You can launch Azure Cloud Shell with:

Option Example/Link
Select Try It in the upper-right corner of a code block. This doesn't automatically copy text to Cloud Shell. Example of Try It for Azure Cloud Shell
Open Azure Cloud Shell in your browser.
Select the Cloud Shell button on the menu in the upper-right corner of the Azure portal. Cloud Shell button in the Azure portal

Create production SQL Database

In this step, you create a SQL Database in Azure. When your app is deployed to Azure, it uses this cloud database.

For SQL Database, this tutorial uses Azure SQL Database.

Create a resource group

A resource group is a logical container into which Azure resources like web apps, databases, and storage accounts are deployed and managed. For example, you can choose to delete the entire resource group in one simple step later.

In the Cloud Shell, create a resource group with the az group create command. The following example creates a resource group named myResourceGroup in the West Europe location. To see all supported locations for App Service on Linux in Basic tier, run the az appservice list-locations --sku B1 --linux-workers-enabled command.

az group create --name myResourceGroup --location "West Europe"

You generally create your resource group and the resources in a region near you.

When the command finishes, a JSON output shows you the resource group properties.

Create a SQL Database logical server

In the Cloud Shell, create a SQL Database logical server with the az sql server create command.

Replace the <server-name> placeholder with a unique SQL Database name. This name is used as the part of the SQL Database endpoint, <server-name>, so the name needs to be unique across all logical servers in Azure. The name must contain only lowercase letters, numbers, and the hyphen (-) character, and must be between 3 and 50 characters long. Also, replace <db-username> and <db-password> with a username and password of your choice.

az sql server create --name <server-name> --resource-group myResourceGroup --location "West Europe" --admin-user <db-username> --admin-password <db-password>

When the SQL Database logical server is created, the Azure CLI shows information similar to the following example:

  "administratorLogin": "sqladmin",
  "administratorLoginPassword": null,
  "fullyQualifiedDomainName": "<server-name>",
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.Sql/servers/<server-name>",
  "identity": null,
  "kind": "v12.0",
  "location": "westeurope",
  "name": "<server-name>",
  "resourceGroup": "myResourceGroup",
  "state": "Ready",
  "tags": null,
  "type": "Microsoft.Sql/servers",
  "version": "12.0"

Configure a server firewall rule

Create an Azure SQL Database server-level firewall rule using the az sql server firewall create command. When both starting IP and end IP are set to, the firewall is only opened for other Azure resources.

az sql server firewall-rule create --resource-group myResourceGroup --server <server-name> --name AllowYourIp --start-ip-address --end-ip-address

Create a database

Create a database with an S0 performance level in the server using the az sql db create command.

az sql db create --resource-group myResourceGroup --server <server-name> --name coreDB --service-objective S0

Create connection string

Replace the following string with the <server-name>, <db-username>, and <db-password> you used earlier.

Server=tcp:<server-name>,1433;Database=coreDB;User ID=<db-username>;Password=<db-password>;Encrypt=true;Connection Timeout=30;

This is the connection string for your .NET Core app. Copy it for use later.

Deploy app to Azure

In this step, you deploy your SQL Database-connected .NET Core application to App Service on Linux.

Configure local git deployment

In the Azure Cloud Shell, configure deployment credentials with the az webapp deployment user set command. You use this deployment user for FTP and local Git deployment to a web app. The username and password are account level. They're different from your Azure subscription credentials.

In the following example, replace <username> and <password>, including the brackets, with a new username and password. The username must be unique within Azure. The password must be at least eight characters long, with two of the following three elements: letters, numbers, and symbols.

az webapp deployment user set --user-name <username> --password <password>

You get a JSON output with the password shown as null. If you get a 'Conflict'. Details: 409 error, change the username. If you get a 'Bad Request'. Details: 400 error, use a stronger password. The deployment username must not contain ‘@’ symbol for local Git pushes.

You configure this deployment user only once. You can use it for all your Azure deployments.


Record the username and password. You need them to deploy the web app later.

Create an App Service plan

In the Cloud Shell, create an App Service plan in the resource group with the az appservice plan create command.

The following example creates an App Service plan named myAppServicePlan in the Basic pricing tier (--sku B1) and in a Linux container (--is-linux).

az appservice plan create --name myAppServicePlan --resource-group myResourceGroup --sku B1 --is-linux

When the App Service plan has been created, the Azure CLI shows information similar to the following example:

  "adminSiteName": null,
  "appServicePlanName": "myAppServicePlan",
  "geoRegion": "West Europe",
  "hostingEnvironmentProfile": null,
  "id": "/subscriptions/0000-0000/resourceGroups/myResourceGroup/providers/Microsoft.Web/serverfarms/myAppServicePlan",
  "kind": "linux",
  "location": "West Europe",
  "maximumNumberOfWorkers": 1,
  "name": "myAppServicePlan",
  < JSON data removed for brevity. >
  "targetWorkerSizeId": 0,
  "type": "Microsoft.Web/serverfarms",
  "workerTierName": null

Create a web app

Create a web app in the myAppServicePlan App Service plan.

In the Cloud Shell, you can use the az webapp create command. In the following example, replace <app-name> with a globally unique app name (valid characters are a-z, 0-9, and -). The runtime is set to DOTNETCORE|2.1. To see all supported runtimes, run az webapp list-runtimes --linux.

# Bash
az webapp create --resource-group myResourceGroup --plan myAppServicePlan --name <app-name> --runtime "DOTNETCORE|2.1" --deployment-local-git
# PowerShell
az --% webapp create --resource-group myResourceGroup --plan myAppServicePlan --name <app-name> --runtime "DOTNETCORE|2.1" --deployment-local-git

When the web app has been created, the Azure CLI shows output similar to the following example:

Local git is configured with url of 'https://<username>@<app-name><app-name>.git'
  "availabilityState": "Normal",
  "clientAffinityEnabled": true,
  "clientCertEnabled": false,
  "cloningInfo": null,
  "containerSize": 0,
  "dailyMemoryTimeQuota": 0,
  "defaultHostName": "<app-name>",
  "deploymentLocalGitUrl": "https://<username>@<app-name><app-name>.git",
  "enabled": true,
  < JSON data removed for brevity. >

You’ve created an empty web app in a Linux container, with git deployment enabled.


The URL of the Git remote is shown in the deploymentLocalGitUrl property, with the format https://<username>@<app-name><app-name>.git. Save this URL as you need it later.

Configure an environment variable

To set connection strings for your Azure app, use the az webapp config appsettings set command in the Cloud Shell. In the following command, replace <app-name>, as well as the <connection-string> parameter with the connection string you created earlier.

az webapp config connection-string set --resource-group myResourceGroup --name <app name> --settings MyDbConnection='<connection-string>' --connection-string-type SQLServer

Next, set ASPNETCORE_ENVIRONMENT app setting to Production. This setting lets you know whether you are running in Azure, because you use SQLite for your local development environment and SQL Database for your Azure environment.

The following example configures a ASPNETCORE_ENVIRONMENT app setting in your Azure app. Replace the <app-name> placeholder.

az webapp config appsettings set --name <app-name> --resource-group myResourceGroup --settings ASPNETCORE_ENVIRONMENT="Production"

Connect to SQL Database in production

In your local repository, open Startup.cs and find the following code:

services.AddDbContext<MyDatabaseContext>(options =>
        options.UseSqlite("Data Source=localdatabase.db"));

Replace it with the following code, which uses the environment variables that you configured earlier.

// Use SQL Database if in Azure, otherwise, use SQLite
if(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Production")
    services.AddDbContext<MyDatabaseContext>(options =>
    services.AddDbContext<MyDatabaseContext>(options =>
            options.UseSqlite("Data Source=MvcMovie.db"));

// Automatically perform database migration

If this code detects that it is running in production (which indicates the Azure environment), then it uses the connection string you configured to connect to the SQL Database. For information on how app settings are accessed in App Service, see Access environment variables.

The Database.Migrate() call helps you when it is run in Azure, because it automatically creates the databases that your .NET Core app needs, based on its migration configuration.

Save your changes, then commit it into your Git repository.

git add .
git commit -m "connect to SQLDB in Azure"

Push to Azure from Git

Back in the local terminal window, add an Azure remote to your local Git repository. Replace <deploymentLocalGitUrl-from-create-step> with the URL of the Git remote that you saved from Create a web app.

git remote add azure <deploymentLocalGitUrl-from-create-step>

Push to the Azure remote to deploy your app with the following command. When prompted for credentials by Git Credential Manager, make sure that you enter the credentials you created in Configure a deployment user, not the credentials you use to sign in to the Azure portal.

git push azure master

This command may take a few minutes to run. While running, it displays information similar to the following example:

Counting objects: 98, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (92/92), done.
Writing objects: 100% (98/98), 524.98 KiB | 5.58 MiB/s, done.
Total 98 (delta 8), reused 0 (delta 0)
remote: Updating branch 'master'.
remote: .
remote: Updating submodules.
remote: Preparing deployment for commit id '0c497633b8'.
remote: Generating deployment script.
remote: Project file path: ./DotNetCoreSqlDb.csproj
remote: Generated deployment script files
remote: Running deployment command...
remote: Handling ASP.NET Core Web Application deployment.
remote: .
remote: .
remote: .
remote: Finished successfully.
remote: Running post deployment command(s)...
remote: Deployment successful.
remote: App container will begin restart within 10 seconds.
To https://<app-name><app-name>.git
 * [new branch]      master -> master

Browse to the Azure app

Browse to the deployed app using your web browser.


Add a few to-do items.

app running in App Service on Linux

Congratulations! You're running a data-driven .NET Core app in App Service on Linux.

Update locally and redeploy

In this step, you make a change to your database schema and publish it to Azure.

Update your data model

Open Models\Todo.cs in the code editor. Add the following property to the ToDo class:

public bool Done { get; set; }

Run Code First Migrations locally

Run a few commands to make updates to your local database.

dotnet ef migrations add AddProperty

Update the local database:

dotnet ef database update

Use the new property

Make some changes in your code to use the Done property. For simplicity in this tutorial, you're only going to change the Index and Create views to see the property in action.

Open Controllers\TodosController.cs.

Find the Create() method and add Done to the list of properties in the Bind attribute. When you're done, your Create() method signature looks like the following code:

public async Task<IActionResult> Create([Bind("ID,Description,CreatedDate,Done")] Todo todo)

Open Views\Todos\Create.cshtml.

In the Razor code, you should see a <div class="form-group"> element for Description, and then another <div class="form-group"> element for CreatedDate. Immediately following these two elements, add another <div class="form-group"> element for Done:

<div class="form-group">
    <label asp-for="Done" class="col-md-2 control-label"></label>
    <div class="col-md-10">
        <input asp-for="Done" class="form-control" />
        <span asp-validation-for="Done" class="text-danger"></span>

Open Views\Todos\Index.cshtml.

Search for the empty <th></th> element. Just above this element, add the following Razor code:

    @Html.DisplayNameFor(model => model.Done)

Find the <td> element that contains the asp-action tag helpers. Just above this element, add the following Razor code:

    @Html.DisplayFor(modelItem => item.Done)

That's all you need to see the changes in the Index and Create views.

Test your changes locally

Run the app locally.

dotnet run

In your browser, navigate to http://localhost:5000/. You can now add a to-do item and check Done. Then it should show up in your homepage as a completed item. Remember that the Edit view doesn't show the Done field, because you didn't change the Edit view.

Publish changes to Azure

git add .
git commit -m "added done field"
git push azure master

Once the git push is complete, navigate to your Azure app and try out the new functionality.

Azure app after Code First Migration

All your existing to-do items are still displayed. When you republish your .NET Core app, existing data in your SQL Database is not lost. Also, Entity Framework Core Migrations only changes the data schema and leaves your existing data intact.

Stream diagnostic logs

The sample project already follows the guidance at ASP.NET Core Logging in Azure with two configuration changes:

  • Includes a reference to Microsoft.Extensions.Logging.AzureAppServices in DotNetCoreSqlDb.csproj.
  • Calls loggerFactory.AddAzureWebAppDiagnostics() in Startup.cs.


The project's log level is set to Information in appsettings.json.

You can access the console logs generated from inside the container. First, turn on container logging by running the following command in the Cloud Shell:

az webapp log config --name <app-name> --resource-group myResourceGroup --docker-container-logging filesystem

Once container logging is turned on, run the following command to see the log stream:

az webapp log tail --name <app-name> --resource-group myResourceGroup

If you don't see console logs immediately, check again in 30 seconds.


You can also inspect the log files from the browser at https://<app-name>

To stop log streaming at any time, type Ctrl+C.

For more information on customizing the ASP.NET Core logs, see Logging in ASP.NET Core.

Manage your Azure app

Go to the Azure portal to see the app you created.

From the left menu, click App Services, then click the name of your Azure app.

Portal navigation to Azure app

By default, the portal shows your app's Overview page. This page gives you a view of how your app is doing. Here, you can also perform basic management tasks like browse, stop, start, restart, and delete. The tabs on the left side of the page show the different configuration pages you can open.

App Service page in Azure portal

Clean up resources

In the preceding steps, you created Azure resources in a resource group. If you don't expect to need these resources in the future, delete the resource group by running the following command in the Cloud Shell:

az group delete --name myResourceGroup

This command may take a minute to run.

Next steps

What you learned:

  • Create a SQL Database in Azure
  • Connect a .NET Core app to SQL Database
  • Deploy the app to Azure
  • Update the data model and redeploy the app
  • Stream logs from Azure to your terminal
  • Manage the app in the Azure portal

Advance to the next tutorial to learn how to map a custom DNS name to your app.

Or, check out other resources: