Deploying .NET Applications to Azure: A Complete Guide
Learn how to deploy your .NET applications to the Azure cloud platform efficiently with this step-by-step guide covering App Service, Functions, Containers, and DevOps.
InSkillCoach
Deploying .NET Applications to Azure: A Complete Guide
Introduction
Microsoft Azure offers a rich, high-performance ecosystem for hosting your .NET applications. Thanks to the native integration between .NET and Azure, you can deploy your applications easily and benefit from automatic scalability, high availability, and enhanced security. This guide walks you through the different deployment options and best practices for optimizing your .NET applications in the cloud.
Prerequisites
Before you begin, make sure you have:
- An Azure account (you can create a free account at azure.microsoft.com)
- The .NET SDK installed on your development machine
- Azure CLI or Azure PowerShell installed (optional but recommended)
- Visual Studio 2022 or Visual Studio Code with the Azure extension
- Git for version control
Azure App Service for .NET Web Applications
Azure App Service is the ideal PaaS (Platform as a Service) solution for hosting your ASP.NET and ASP.NET Core web applications.
Creating an App Service from the Azure Portal
- Sign in to the Azure Portal
- Click “Create a resource” > “Web” > “App Service”
- Fill in the basic information:
- Resource group: create a new one or use an existing one
- App name: must be globally unique across Azure
- Publish: select “Code”
- Runtime stack: choose ”.NET 6” (or the version you are using)
- Operating system: Windows or Linux
- Region: choose the one closest to your users
- App Service plan: select an existing plan or create a new one
- Click “Review + create,” then “Create”
Deploying from Visual Studio
- Open your solution in Visual Studio
- Right-click the web project and select “Publish”
- Choose “Azure” as the target
- Select “Azure App Service,” then the instance you just created
- Configure the deployment settings and click “Publish”
Deploying with Azure DevOps
# azure-pipelines.yml
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Release'
webAppName: 'votre-app-service'
steps:
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '6.x'
- script: dotnet build --configuration $(buildConfiguration)
displayName: 'dotnet build $(buildConfiguration)'
- task: DotNetCoreCLI@2
inputs:
command: 'publish'
publishWebProjects: true
arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)'
zipAfterPublish: true
- task: AzureWebApp@1
inputs:
azureSubscription: 'votre-connexion-azure'
appName: '$(webAppName)'
package: '$(Build.ArtifactStagingDirectory)/*.zip'
Environment Configuration
Use application settings to configure your application without recompiling:
- In the Azure portal, go to your App Service
- Under “Configuration” > “Application settings,” add your environment variables
- For example, for a database connection string:
- Name: ConnectionStrings__DefaultConnection
- Value: your connection string
Azure Functions for Serverless Microservices
Azure Functions lets you run small pieces of code without managing the underlying infrastructure.
Creating a Function App
// Simple Function App that responds to HTTP requests
public static class HttpExample
{
[FunctionName("HttpExample")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
string responseMessage = string.IsNullOrEmpty(name)
? "Cette fonction HTTP a été exécutée avec succès. Passez un nom dans la requête pour obtenir un message personnalisé."
: $"Bonjour, {name}. Cette fonction HTTP a été exécutée avec succès.";
return new OkObjectResult(responseMessage);
}
}
Deploying Azure Functions
From Visual Studio
- Create an Azure Functions project
- Develop your functions
- Right-click the project > “Publish”
- Choose Azure as the target
- Select or create a Function App
Using Azure CLI
# Sign in to Azure
az login
# Create a resource group (if needed)
az group create --name MonGroupeDeRessources --location francecentral
# Create a Function App
az functionapp create --resource-group MonGroupeDeRessources --consumption-plan-location francecentral --runtime dotnet --functions-version 4 --name MonAppDeFonctions --storage-account monstockage
# Deploy the code
func azure functionapp publish MonAppDeFonctions
Containerization with Docker and Azure Container Registry
Containerizing your .NET applications provides portability and consistency across environments.
Creating a Dockerfile for ASP.NET Core
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["MonApp.csproj", "./"]
RUN dotnet restore "MonApp.csproj"
COPY . .
RUN dotnet build "MonApp.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "MonApp.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MonApp.dll"]
Creating and Using Azure Container Registry (ACR)
# Create a container registry
az acr create --resource-group MonGroupeDeRessources --name monregistre --sku Basic
# Sign in to the registry
az acr login --name monregistre
# Build the Docker image
docker build -t monapp:v1 .
# Tag the image for ACR
docker tag monapp:v1 monregistre.azurecr.io/monapp:v1
# Push the image to ACR
docker push monregistre.azurecr.io/monapp:v1
Deploying to Azure App Service with Containers
# Enable admin access for the registry
az acr update -n monregistre --admin-enabled true
# Get the registry credentials
az acr credential show -n monregistre
# Create an App Service plan that supports containers
az appservice plan create --resource-group MonGroupeDeRessources --name MonPlanAppService --is-linux --sku B1
# Create an App Service that uses the container
az webapp create --resource-group MonGroupeDeRessources --plan MonPlanAppService --name MonAppWeb --deployment-container-image-name monregistre.azurecr.io/monapp:v1
# Configure the registry credentials
az webapp config container set --name MonAppWeb --resource-group MonGroupeDeRessources --docker-custom-image-name monregistre.azurecr.io/monapp:v1 --docker-registry-server-url https://monregistre.azurecr.io --docker-registry-server-user monregistre --docker-registry-server-password <mot-de-passe>
Azure Kubernetes Service (AKS) for .NET Applications
AKS is ideal for complex applications that require advanced container orchestration.
Deploying a .NET Application to AKS
- Create an AKS cluster:
az aks create --resource-group MonGroupeDeRessources --name MonClusterAKS --node-count 2 --enable-addons monitoring --generate-ssh-keys
- Connect to the cluster:
az aks get-credentials --resource-group MonGroupeDeRessources --name MonClusterAKS
- Create a Kubernetes deployment file (deployment.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
name: monapp
spec:
replicas: 3
selector:
matchLabels:
app: monapp
template:
metadata:
labels:
app: monapp
spec:
containers:
- name: monapp
image: monregistre.azurecr.io/monapp:v1
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: monapp
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: monapp
- Deploy the application to AKS:
kubectl apply -f deployment.yaml
- Verify that the service is accessible:
kubectl get services monapp
Azure Databases for .NET Applications
Azure SQL Database with Entity Framework Core
-
Create an Azure SQL database from the Azure portal
-
Configure the connection string in your application:
// appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Server=tcp:monserveur.database.windows.net,1433;Database=maBaseDeDonnees;User ID=monutilisateur;Password=monMotDePasse;Encrypt=true;Connection Timeout=30;"
}
}
- Use Entity Framework Core to connect:
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
// ...
}
Azure Cosmos DB for NoSQL
// Cosmos DB client configuration
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<CosmosClient>(serviceProvider => {
var configuration = serviceProvider.GetRequiredService<IConfiguration>();
var cosmosDbSection = configuration.GetSection("CosmosDb");
var endpoint = cosmosDbSection["Endpoint"];
var key = cosmosDbSection["Key"];
return new CosmosClient(endpoint, key);
});
services.AddSingleton<IDocumentRepository, CosmosDbRepository>();
}
CI/CD for .NET Applications with GitHub Actions
GitHub Actions Workflow for App Service
# .github/workflows/azure-webapps-dotnet.yml
name: .NET Core CI/CD pour Azure Web App
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
env:
AZURE_WEBAPP_NAME: votre-app-service
AZURE_WEBAPP_PACKAGE_PATH: '.'
DOTNET_VERSION: '6.0.x'
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Configurer .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Restaurer les dépendances
run: dotnet restore
- name: Build
run: dotnet build --configuration Release --no-restore
- name: Test
run: dotnet test --no-restore --verbosity normal
- name: Publish
run: dotnet publish -c Release -o ${{env.AZURE_WEBAPP_PACKAGE_PATH}}/myapp
- name: Déployer sur Azure Web App
uses: azure/webapps-deploy@v2
with:
app-name: ${{ env.AZURE_WEBAPP_NAME }}
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
package: ${{env.AZURE_WEBAPP_PACKAGE_PATH}}/myapp
Monitoring and Diagnostics
Application Insights for Monitoring
-
Create an Application Insights resource in the Azure portal
-
Integrate Application Insights into your application:
// Program.cs (.NET 6)
var builder = WebApplication.CreateBuilder(args);
// Add Application Insights
builder.Services.AddApplicationInsightsTelemetry();
// ...
var app = builder.Build();
- Add custom logs:
// In a controller or service
public class MonController : Controller
{
private readonly ILogger<MonController> _logger;
public MonController(ILogger<MonController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
_logger.LogInformation("La page d'accueil a été visitée");
return View();
}
}
- View the metrics in the Azure Application Insights portal
Securing .NET Applications on Azure
Using Azure Key Vault
-
Create a key vault in the Azure portal
-
Grant permissions to your application:
az keyvault set-policy --name MonCoffre --object-id <object-id-de-votre-app> --secret-permissions get list
- Integrate Key Vault into your application:
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// Add the Azure Key Vault configuration
builder.Configuration.AddAzureKeyVault(
new Uri($"https://{builder.Configuration["KeyVault:VaultName"]}.vault.azure.net/"),
new DefaultAzureCredential());
Setting Up Azure AD B2C for Authentication
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAdB2C"));
// ...
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
Cost Optimization
Tips for Reducing Costs on Azure
-
Choose the right pricing tier:
- Use the Free and Shared tiers for development
- Consider Basic/Standard for small to medium-sized production workloads
-
Scale automatically:
- Configure autoscaling based on your needs
az monitor autoscale create --resource-group MonGroupeDeRessources --resource monappservice --resource-type "Microsoft.Web/sites" --name autoscale-config --min-count 1 --max-count 5 --count 1 -
Use reserved instances for long-term savings
-
Enable Azure Cost Management to monitor and optimize spending
-
Clean up unused resources regularly
Best Practices for .NET on Azure
-
Cloud-native architecture:
- Design for resilience and scalability
- Use serverless architectures when appropriate
-
Externalized configuration:
- Store settings in Azure App Configuration or Key Vault
- Use environment variables for environment-specific configurations
-
Comprehensive monitoring:
- Integrate Application Insights from the start
- Configure alerts for critical metrics
-
Automated testing:
- Include load tests specifically for Azure
- Use test/staging environments
-
Infrastructure as Code (IaC):
- Use Azure Resource Manager (ARM) or Terraform
// example ARM template { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "appServiceName": { "type": "string", "metadata": { "description": "Nom de l'App Service" } } }, "resources": [ { "type": "Microsoft.Web/serverfarms", "apiVersion": "2020-06-01", "name": "[parameters('appServiceName')]", "location": "[resourceGroup().location]", "sku": { "name": "B1", "tier": "Basic" } } ] }
Conclusion
Azure offers a rich, integrated ecosystem for your .NET applications, covering the entire development lifecycle. By combining Azure services with .NET development best practices, you can build robust, high-performing, and scalable applications.
The tools and services presented in this guide are only the beginning of what Azure can offer .NET developers. Don’t hesitate to explore further and combine different services to meet your application’s specific needs.
Additional Resources
About InSkillCoach
Training and technology expert
Coach specializing in advanced technologies and AI, backed by GNeurone Inc.
Certifications:
- AWS Certified Solutions Architect – Professional
- Google Cloud certifications
- Microsoft Certified: DevOps Engineer Expert
- Certified Kubernetes Administrator (CKA)
- CompTIA Security+
Comments
Comments are powered by GitHub Discussions
Sign in with GitHub to join the discussion