From dotnet-blazor
Deploys .NET apps to Azure Container Apps via Aspire/azd, App Service, Docker, Kubernetes using multi-stage Dockerfiles, Compose, and GitHub Actions CI/CD.
How this skill is triggered — by the user, by Claude, or both
Slash command
/dotnet-blazor:cloud-native-deployThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
```bash
# Install Azure Developer CLI
winget install microsoft.azd # Windows
brew install azd # macOS
# Initialize and deploy
azd init
azd provision # Creates Azure resources from Aspire manifest
azd deploy # Deploys all services
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
# Copy and restore
COPY *.sln .
COPY */*.csproj ./
RUN for file in *.csproj; do mkdir -p ${file%.*}/ && mv $file ${file%.*}/; done
RUN dotnet restore
# Build and publish
COPY . .
RUN dotnet publish src/MyApp.Web/MyApp.Web.csproj -c Release -o /app/publish --no-restore
# Runtime
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
WORKDIR /app
EXPOSE 8080
ENV ASPNETCORE_URLS=http://+:8080
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "MyApp.Web.dll"]
services:
web:
build:
context: .
dockerfile: src/MyApp.Web/Dockerfile
ports:
- "8080:8080"
environment:
- ConnectionStrings__Default=Host=db;Database=myapp;Username=postgres;Password=postgres
- ASPNETCORE_ENVIRONMENT=Development
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
environment:
POSTGRES_DB: myapp
POSTGRES_PASSWORD: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data:
name: CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
DOTNET_VERSION: '10.0.x'
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- run: dotnet restore
- run: dotnet build --no-restore -c Release -warnaserror
- run: dotnet test --no-build -c Release --logger trx --results-directory TestResults
- uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: TestResults
deploy:
needs: build-and-test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- run: |
dotnet publish -c Release -o ./publish
az webapp deploy --resource-group myapp-rg --name myapp-web --src-path ./publish
// Program.cs - environment-specific config
builder.Configuration
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables()
.AddUserSecrets<Program>(optional: true); // Development only
// Health check endpoint for load balancer
app.MapHealthChecks("/health");
az login
az webapp up --sku F1 --name <app-name> --os-type linux
# --sku: F1 (free), B1 (basic), S1 (standard), P1v3 (premium)
# app-name must be globally unique (a-z, 0-9, -)
azd init --template https://github.com/Azure-Samples/quickstart-deploy-aspnet-core-app-service.git
azd up # Provisions + deploys
azd down # Cleanup all resources
Connect-AzAccount
dotnet publish --configuration Release
Compress-Archive -Path bin\Release\net10.0\publish\* -DestinationPath deploy.zip
Publish-AzWebApp -ResourceGroupName myRG -Name <app-name> -ArchivePath deploy.zip -Force
// 4-step pattern: Locate → Install → Create client → Call methods
// Blob Storage
using Azure.Storage.Blobs;
var client = new BlobContainerClient(
new Uri("https://<account>.blob.core.windows.net/<container>"),
new DefaultAzureCredential());
await client.UploadBlobAsync("file.txt", File.OpenRead("local.txt"));
// Key Vault
using Azure.Security.KeyVault.Secrets;
var kvClient = new SecretClient(
new Uri("https://<vault>.vault.azure.net/"),
new DefaultAzureCredential());
var secret = await kvClient.GetSecretAsync("my-secret");
// Service Bus
using Azure.Messaging.ServiceBus;
var sbClient = new ServiceBusClient("<connection-string>");
var sender = sbClient.CreateSender("queue-name");
await sender.SendMessageAsync(new ServiceBusMessage("Hello"));
| Use Case | Azure Service | NuGet Package |
|---|---|---|
| Web apps, APIs | App Service | - |
| Serverless microservices | Container Apps | - |
| Event-driven functions | Azure Functions | Azure.Functions |
| Relational data | Azure SQL | Microsoft.Data.SqlClient |
| Global NoSQL | Cosmos DB | Azure.Cosmos |
| File/blob storage | Blob Storage | Azure.Storage.Blobs |
| Messaging queues | Service Bus | Azure.Messaging.ServiceBus |
| Secrets management | Key Vault | Azure.Security.KeyVault.Secrets |
| Authentication | Entra ID | Microsoft.Identity.Web |
| Caching | Redis | StackExchange.Redis |
\bin folder<!-- Single target (recommended for apps) -->
<TargetFramework>net10.0</TargetFramework>
<!-- Multi-target (for NuGet libraries needing broad reach) -->
<TargetFrameworks>net10.0;netstandard2.0;net462</TargetFrameworks>
Anti-pattern: Don't target netstandard1.x - creates massive dependency graph.
npx claudepluginhub markus41/claude --plugin dotnet-blazorDeploys .NET Aspire apps from AppHost models to Docker Compose, Kubernetes, Azure, or AWS using the Aspire CLI. Routes deployment tasks away from generic cloud tools when Aspire markers are present.
Orchestrates cloud-native .NET distributed apps with Aspire AppHost, integrates components like Postgres/Redis/RabbitMQ, adds telemetry, service discovery, and health checks.
Deploying .NET containers. Kubernetes probes, Docker Compose for local dev, CI/CD integration.