Table of Contents

Web API Sample (MinimalApi)

This sample demonstrates how to containerize an ASP.NET Core Minimal API application using JD.MSBuild.Containers.

Overview

Project Type: ASP.NET Core Minimal API
Location: samples/MinimalApi/
Image Name: minimal-api-sample
Default Port: 8080

What This Sample Demonstrates

  • ✅ RESTful API containerization
  • ✅ Swagger/OpenAPI integration
  • ✅ Health check endpoints
  • ✅ JSON response handling
  • ✅ Automatic port exposure
  • ✅ Hot reload in development

Project Structure

MinimalApi/
├── Program.cs              # Application entry point
├── MinimalApi.csproj       # Project file with Docker config
├── Dockerfile              # Auto-generated
├── appsettings.json        # Configuration
└── appsettings.Development.json

Docker Configuration

The MinimalApi.csproj includes Docker settings:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    
    <!-- Docker Configuration -->
    <DockerEnabled>true</DockerEnabled>
    <DockerImageName>minimal-api-sample</DockerImageName>
    <DockerImageTag>latest</DockerImageTag>
    <DockerBuildOnPublish>true</DockerBuildOnPublish>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="JD.MSBuild.Containers" Version="*" />
  </ItemGroup>
</Project>

API Endpoints

GET /

Returns service status.

Response:

{
  "message": "Minimal API is running",
  "timestamp": "2026-01-17T05:30:00Z"
}

GET /health

Health check endpoint for monitoring.

Response:

{
  "status": "Healthy"
}

GET /weatherforecast

Returns sample weather data.

Response:

[
  {
    "date": "2026-01-18",
    "temperatureC": 25,
    "temperatureF": 76,
    "summary": "Warm"
  }
]

Building and Running

Local Development (Without Docker)

cd samples/MinimalApi
dotnet run

Browse to: http://localhost:5000

Build Docker Image

# Generate Dockerfile and build image
dotnet publish --configuration Release

# Verify image was created
docker images | grep minimal-api-sample

Run Container

# Run in detached mode
docker run -d -p 8080:8080 --name minimalapi minimal-api-sample:latest

# View logs
docker logs minimalapi

# Test endpoints
curl http://localhost:8080/health
curl http://localhost:8080/weatherforecast

# Stop container
docker stop minimalapi
docker rm minimalapi

Run with Environment Variables

docker run -d -p 8080:8080 \
  -e ASPNETCORE_ENVIRONMENT=Development \
  -e Logging__LogLevel__Default=Debug \
  --name minimalapi \
  minimal-api-sample:latest

Swagger UI

The API includes Swagger/OpenAPI documentation:

Accessing Swagger

When running locally:

http://localhost:5000/swagger

When running in container:

http://localhost:8080/swagger

Enabling Swagger in Production

By default, Swagger is only enabled in Development. To enable in containers:

// Program.cs
if (app.Environment.IsDevelopment() || app.Environment.IsStaging())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

Or set environment variable:

docker run -e ASPNETCORE_ENVIRONMENT=Development minimal-api-sample:latest

Health Checks

The API implements ASP.NET Core health checks:

// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();

var app = builder.Build();
app.MapHealthChecks("/health");

Testing Health Endpoint

# Should return "Healthy"
curl http://localhost:8080/health

# In Docker health check
docker run --health-cmd="curl --fail http://localhost:8080/health || exit 1" \
  --health-interval=30s \
  --health-timeout=3s \
  --health-retries=3 \
  minimal-api-sample:latest

Generated Dockerfile

The auto-generated Dockerfile includes:

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 8080

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

FROM build AS publish
RUN dotnet publish "MinimalApi.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MinimalApi.dll"]

Customization Examples

Custom Port

<PropertyGroup>
  <DockerExposePort>5000</DockerExposePort>
</PropertyGroup>

Run with: docker run -p 5000:5000 minimal-api-sample:latest

Custom Image Tag

<PropertyGroup>
  <DockerImageTag>v1.0.0</DockerImageTag>
</PropertyGroup>

Alpine Base Image

<PropertyGroup>
  <DockerBaseImageRuntime>mcr.microsoft.com/dotnet/aspnet:8.0-alpine</DockerBaseImageRuntime>
</PropertyGroup>

Integration with Docker Compose

Example docker-compose.yml:

version: '3.8'

services:
  api:
    image: minimal-api-sample:latest
    ports:
      - "8080:8080"
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - Logging__LogLevel__Default=Information
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 3s
      retries: 3

Run with:

docker-compose up -d

Deployment Examples

Azure Container Instances

az container create \
  --resource-group myResourceGroup \
  --name minimalapi \
  --image minimal-api-sample:latest \
  --dns-name-label minimalapi-unique \
  --ports 8080

Kubernetes

apiVersion: apps/v1
kind: Deployment
metadata:
  name: minimalapi
spec:
  replicas: 3
  selector:
    matchLabels:
      app: minimalapi
  template:
    metadata:
      labels:
        app: minimalapi
    spec:
      containers:
      - name: api
        image: minimal-api-sample:latest
        ports:
        - containerPort: 8080
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
  name: minimalapi-service
spec:
  selector:
    app: minimalapi
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  type: LoadBalancer

Apply with:

kubectl apply -f minimalapi-deployment.yaml

Monitoring

Logging

View container logs:

docker logs -f minimalapi

Performance Testing

Using Apache Bench:

ab -n 1000 -c 10 http://localhost:8080/weatherforecast

Using hey:

hey -n 1000 -c 10 http://localhost:8080/weatherforecast

Troubleshooting

Port Already in Use

If port 8080 is already in use:

docker run -p 8081:8080 minimal-api-sample:latest

Cannot Connect to API

Check if container is running:

docker ps | grep minimal-api-sample

Check container logs:

docker logs minimalapi

Test from inside container:

docker exec -it minimalapi curl http://localhost:8080/health

Slow Container Startup

Increase health check initial delay:

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
  interval: 30s
  timeout: 3s
  retries: 3
  start_period: 40s  # Give container time to start

Next Steps