← Back to Blog Azure

Deploying .NET Microservices to Azure AKS with Helm and GitHub Actions

Saurav Rai

Founder & Lead Architect

· · 15 min read

Overview

Complete CI/CD walkthrough: containerise .NET, write Helm charts, configure AKS, and automate deployment.

Multi-Stage Docker Build

Efficient Docker images for .NET require multi-stage builds. The SDK stage compiles and publishes your app; the runtime stage contains only the published output. This takes a typical .NET image from 800MB to under 120MB.

Use Microsoft's chiseled images for maximum security and minimal size—they contain only the .NET runtime with no shell or package manager.

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["MyApp/MyApp.csproj", "MyApp/"]
RUN dotnet restore "MyApp/MyApp.csproj"
COPY . .
RUN dotnet publish "MyApp/MyApp.csproj" -c Release -o /app/publish

FROM mcr.microsoft.com/dotnet/aspnet:8.0-jammy-chiseled
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "MyApp.dll"]

Helm Chart Structure

Helm charts template Kubernetes manifests with environment-specific values. A typical .NET service chart includes a Deployment, Service, HorizontalPodAutoscaler, and Ingress resource.

We maintain a shared base chart for all Omni Stack microservices with standardised health check paths, resource limits, and pod disruption budgets—ensuring consistency across services.

  • templates/deployment.yaml - Pod spec and replicas
  • templates/service.yaml - ClusterIP service
  • templates/hpa.yaml - Auto-scaling rules
  • templates/ingress.yaml - External routing
  • values.yaml - Environment-specific overrides

GitHub Actions Pipeline

A production pipeline for AKS deployment has three key stages: build and push the Docker image, run integration tests against the image, and deploy to staging before production with a manual approval gate.

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: azure/login@v1
      - uses: azure/docker-login@v1
      - run: docker build -t myregistry.azurecr.io/myapp:${{ github.sha }} .
      - run: docker push myregistry.azurecr.io/myapp:${{ github.sha }}
  deploy:
    needs: build
    environment: production
    steps:
      - uses: azure/aks-set-context@v3
      - run: helm upgrade --install myapp ./charts/myapp --set image.tag=${{ github.sha }}

Key Takeaways

  • Use multi-stage builds to minimise image size
  • Chiseled base images improve security
  • Helm enables environment-specific deployments
  • Use GitHub Environments for production approval gates
  • Always set resource requests and limits in Kubernetes

Saurav Rai

Founder & Lead Architect, Omni Stack

7+ years building enterprise .NET and cloud applications for clients across Australia, USA, and the Middle East. Passionate about clean architecture, developer experience, and shipping fast.

.NET / Blazor · 12 min read

Blazor Auto Render Mode: Server vs WebAssembly Per Component

.NET 8 per-component interactivity: our production guide to choosing Server vs WASM—with benchmarks.

Read More →
.NET / Blazor · 8 min read

Building Real-Time Dashboards with SignalR and Blazor Server

Step-by-step: live-updating dashboards using SignalR Hub groups, Blazor Server, and efficient diff rendering.

Read More →
AI / ML · 14 min read

Building a RAG Chatbot with Azure OpenAI and AI Search

Production RAG implementation: chunking strategies, hybrid search, re-ranking, and grounding verification.

Read More →