Key Best Practices
- Use multistage builds to keep images small and avoid shipping build tools.
- Base image selection: prefer
mcr.microsoft.com/dotnet/aspnet:8.0-alpine for runtime.
- Leverage .dockerignore to exclude source, bin, obj, and test files.
- Set a non‑root user to run the container for security.
- Expose only required ports and use
HEALTHCHECK to monitor container health.
- Use environment variables for configuration and secrets via Docker secrets or Kubernetes.
- Limit layers by combining related RUN commands.
Sample Multistage Dockerfile
# syntax=docker/dockerfile:1
FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
WORKDIR /src
COPY ["MyApp.csproj", "./"]
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app --no-restore
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS runtime
WORKDIR /app
COPY --from=build /app ./
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost/health || exit 1
ENTRYPOINT ["dotnet", "MyApp.dll"]
Performance Tuning
| Setting | Recommendation |
| ThreadPool Min Threads | Set to CPU count × 2 |
| ReadyToRun | Enable by adding /p:ReadyToRun=true |
| Trim Assemblies | Use /p:PublishTrimmed=true for self‑contained images |
| Docker Layer Caching | Leverage CI/CD cache to speed up rebuilds |
Reference Links