plugins/dotnet-blazor/skills/docker-containers/SKILL.md
Multi-container .NET applications with Docker Compose, container orchestration, and development environments
npx skillsauth add markus41/claude docker-containersInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
# Build stage
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
# Copy solution and project files for layer caching
COPY *.sln .
COPY Directory.Build.props Directory.Packages.props ./
COPY src/MyApp.Web/MyApp.Web.csproj src/MyApp.Web/
COPY src/MyApp.Api/MyApp.Api.csproj src/MyApp.Api/
COPY src/MyApp.Domain/MyApp.Domain.csproj src/MyApp.Domain/
COPY src/MyApp.Infrastructure/MyApp.Infrastructure.csproj src/MyApp.Infrastructure/
RUN dotnet restore
# Copy source and publish
COPY . .
RUN dotnet publish src/MyApp.Web/MyApp.Web.csproj -c Release -o /app/publish --no-restore
# Runtime stage (minimal image)
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
WORKDIR /app
EXPOSE 8080
ENV ASPNETCORE_URLS=http://+:8080
ENV DOTNET_RUNNING_IN_CONTAINER=true
# Non-root user for security
USER $APP_UID
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "MyApp.Web.dll"]
services:
# Blazor Web App
webapp:
build:
context: .
dockerfile: src/MyApp.Web/Dockerfile
ports:
- "5000:8080"
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ConnectionStrings__Default=Host=postgres;Database=myapp;Username=postgres;Password=devpass
- ConnectionStrings__Redis=redis:6379
- RabbitMQ__Host=rabbitmq
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
volumes:
- ~/.aspnet/https:/https:ro # Dev HTTPS certs
networks:
- backend
# API Service
api:
build:
context: .
dockerfile: src/MyApp.Api/Dockerfile
ports:
- "5001:8080"
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ConnectionStrings__Default=Host=postgres;Database=myapp;Username=postgres;Password=devpass
- ConnectionStrings__Redis=redis:6379
depends_on:
postgres:
condition: service_healthy
networks:
- backend
# Worker Service
worker:
build:
context: .
dockerfile: src/MyApp.Worker/Dockerfile
environment:
- ConnectionStrings__Default=Host=postgres;Database=myapp;Username=postgres;Password=devpass
- RabbitMQ__Host=rabbitmq
depends_on:
postgres:
condition: service_healthy
rabbitmq:
condition: service_healthy
networks:
- backend
# PostgreSQL
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: myapp
POSTGRES_USER: postgres
POSTGRES_PASSWORD: devpass
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
networks:
- backend
# Redis
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- backend
# RabbitMQ
rabbitmq:
image: rabbitmq:3-management-alpine
ports:
- "5672:5672" # AMQP
- "15672:15672" # Management UI
environment:
RABBITMQ_DEFAULT_USER: guest
RABBITMQ_DEFAULT_PASS: guest
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "check_port_connectivity"]
interval: 10s
timeout: 5s
retries: 5
networks:
- backend
# SQL Server (alternative to PostgreSQL)
# sqlserver:
# image: mcr.microsoft.com/mssql/server:2022-latest
# environment:
# ACCEPT_EULA: "Y"
# MSSQL_SA_PASSWORD: "YourStrong!Password"
# ports:
# - "1433:1433"
volumes:
postgres_data:
redis_data:
networks:
backend:
driver: bridge
// Integration event (crosses service boundaries)
public sealed record OrderPaymentSucceededIntegrationEvent(
int OrderId, DateTime PaymentDate) : IntegrationEvent;
// Event bus interface
public interface IEventBus
{
Task PublishAsync<T>(T @event, CancellationToken ct = default) where T : IntegrationEvent;
void Subscribe<T, THandler>() where T : IntegrationEvent where THandler : IIntegrationEventHandler<T>;
}
// Integration event handler
public sealed class OrderPaymentSucceededHandler(
IOrderRepository orderRepo,
ILogger<OrderPaymentSucceededHandler> logger)
: IIntegrationEventHandler<OrderPaymentSucceededIntegrationEvent>
{
public async Task Handle(OrderPaymentSucceededIntegrationEvent @event, CancellationToken ct)
{
logger.LogInformation("Payment succeeded for order {OrderId}", @event.OrderId);
var order = await orderRepo.GetAsync(@event.OrderId, ct);
order?.SetPaidStatus();
await orderRepo.UnitOfWork.SaveEntitiesAsync(ct);
}
}
// Using YARP (Yet Another Reverse Proxy) - Microsoft's recommended gateway
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
var app = builder.Build();
app.MapReverseProxy();
app.Run();
// appsettings.json for YARP
{
"ReverseProxy": {
"Routes": {
"catalog-route": {
"ClusterId": "catalog-cluster",
"Match": { "Path": "/api/catalog/{**catch-all}" }
},
"ordering-route": {
"ClusterId": "ordering-cluster",
"Match": { "Path": "/api/orders/{**catch-all}" }
}
},
"Clusters": {
"catalog-cluster": {
"Destinations": {
"destination1": { "Address": "http://catalog-api:8080/" }
}
},
"ordering-cluster": {
"Destinations": {
"destination1": { "Address": "http://ordering-api:8080/" }
}
}
}
}
}
| Image | Use for | Size |
|-------|---------|------|
| mcr.microsoft.com/dotnet/sdk:10.0 | Build stage only | ~800MB |
| mcr.microsoft.com/dotnet/aspnet:10.0 | Web apps, APIs | ~220MB |
| mcr.microsoft.com/dotnet/runtime:10.0 | Console/worker apps | ~190MB |
| mcr.microsoft.com/dotnet/runtime-deps:10.0 | Self-contained AOT | ~110MB |
.dockerignore to exclude bin/, obj/, .git/:latest alone in production)tools
Build Teams-native agents with the Teams SDK (formerly Teams AI Library v2) — App class, activity routing, adaptive cards, streaming, AI-generated labels, feedback, message extensions, Teams-as-MCP-server, and the bring-your-own-AI pattern with Agent Framework.
tools
Run agents on Microsoft Foundry (formerly Azure AI Foundry) Agent Service — prompt agents vs hosted agents, threads/runs and the Responses API, built-in tools (Bing grounding, code interpreter, file search, MCP, OpenAPI, A2A), connected agents, Entra agent identity, SDKs, and observability/evaluations.
tools
Build and host custom engine agents with the Microsoft 365 Agents SDK — AgentApplication, the Activity protocol, channel reach via Azure Bot Service, hosting Agent Framework or Semantic Kernel engines, and the Agents Toolkit/Playground workflow. Successor to the Bot Framework SDK.
tools
Design, govern, and extend Microsoft Copilot Studio agents — topics, generative orchestration, knowledge, tools and MCP, agent flows, autonomous triggers, publishing channels, Copilot Credits pricing, and solution-based ALM on Power Platform.