Docker — Containerizing .NET API

লেসন ৪৭ / ৫০

কেন Docker?

"Works on my machine" সমস্যা সমাধান — code + dependencies + runtime container-এ pack। যেখানেই চালান, একই behavior।

Multi-Stage Dockerfile ⭐

# Build stage
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["MyApp.Api/MyApp.Api.csproj", "MyApp.Api/"]
COPY ["MyApp.Application/MyApp.Application.csproj", "MyApp.Application/"]
COPY ["MyApp.Domain/MyApp.Domain.csproj", "MyApp.Domain/"]
RUN dotnet restore "MyApp.Api/MyApp.Api.csproj"

COPY . .
WORKDIR "/src/MyApp.Api"
RUN dotnet build "MyApp.Api.csproj" -c Release -o /app/build

# Publish stage
FROM build AS publish
RUN dotnet publish "MyApp.Api.csproj" -c Release -o /app/publish /p:UseAppHost=false

# Runtime stage (small image)
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
WORKDIR /app
COPY --from=publish /app/publish .
EXPOSE 8080
ENV ASPNETCORE_URLS=http://+:8080
ENTRYPOINT ["dotnet", "MyApp.Api.dll"]

.dockerignore

**/bin/
**/obj/
**/.vs/
**/.vscode/
**/.idea/
**/*.user
**/.git/
.gitignore
README.md
Dockerfile
.dockerignore

Build & Run

# Build image
docker build -t myapp-api:1.0 .

# Run container
docker run -d -p 8080:8080 --name myapp myapp-api:1.0

# Logs
docker logs -f myapp

# Stop & remove
docker stop myapp && docker rm myapp

docker-compose.yml ⭐

version: '3.8'
services:
  api:
    build: .
    ports:
      - "8080:8080"
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ConnectionStrings__Default=Server=db;Database=Shop;User=sa;Password=Yourpass!;TrustServerCertificate=True
    depends_on:
      - db
      - redis

  db:
    image: mcr.microsoft.com/mssql/server:2022-latest
    environment:
      - ACCEPT_EULA=Y
      - SA_PASSWORD=Yourpass!
    ports:
      - "1433:1433"
    volumes:
      - sqldata:/var/opt/mssql

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  sqldata:

Run Compose

docker compose up -d
docker compose ps
docker compose logs -f api
docker compose down

Health Check

# Dockerfile
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
    CMD curl -f http://localhost:8080/health || exit 1

# Program.cs
builder.Services.AddHealthChecks()
    .AddDbContextCheck<AppDbContext>()
    .AddRedis(builder.Configuration.GetConnectionString("Redis"));

app.MapHealthChecks("/health");

Production Tips

  • Use Alpine base image for smaller size: aspnet:8.0-alpine
  • Run as non-root user for security
  • Use secrets via env vars, never hardcode
  • Tag images with version + git SHA
  • Push to registry: Docker Hub / Azure Container Registry / AWS ECR

Push to Registry

docker tag myapp-api:1.0 myorg/myapp-api:1.0
docker push myorg/myapp-api:1.0