Deployment
|
This section documents ASP.NET Core on .NET 10 (LTS), the current release — the minimal hosting model, the middleware pipeline, dependency injection, Minimal APIs, MVC & Razor Pages, Blazor with the current render modes, SignalR and gRPC, EF Core, ASP.NET Core Identity and policy-based authorization, output caching, rate limiting, and Native-AOT-aware building — as described by the official documentation at Microsoft Learn, which is the reference these pages are written and verified against. This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. .NET ships a major release every November and its APIs continue to evolve: the examples here target .NET 10 / C# 14. This section’s bibliography lists the reference material consulted while preparing these pages. |
Deployment is dotnet publish plus a host that runs the output. See
Host and deploy ASP.NET Core.
dotnet publish
dotnet publish -c Release -o ./publish # framework-dependent (needs .NET runtime on host)
dotnet publish -c Release -r linux-x64 --self-contained # bundles the runtime, RID-specific
# size / startup options
dotnet publish -c Release -r linux-x64 -p:PublishTrimmed=true -p:PublishReadyToRun=true
dotnet publish -c Release -r linux-x64 -p:PublishAot=true # Native AOT (Minimal APIs)
dotnet publish -c Release /t:PublishContainer # build an OCI image, no Dockerfile
<PropertyGroup>
<PublishReadyToRun>true</PublishReadyToRun>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
Publish profiles (Properties/PublishProfiles/*.pubxml) capture a target’s settings for repeatable publishes.
See .NET application deployment.
IIS (Windows)
The ASP.NET Core Module forwards requests from IIS to the app. Publishing a Web SDK project emits a
web.config that configures it. Use the in-process hosting model (default) unless you need
out-of-process. Create an app pool with "No Managed Code". See
Host ASP.NET Core on Windows with IIS.
Linux
Run Kestrel as a service behind Nginx (TLS termination + reverse proxy):
# /etc/systemd/system/shop.service
[Service]
WorkingDirectory=/var/www/shop
ExecStart=/usr/bin/dotnet /var/www/shop/Shop.Web.dll
Restart=always
Environment=ASPNETCORE_ENVIRONMENT=Production
User=www-data
server {
listen 443 ssl;
server_name shop.example.com;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
AddWindowsService() / AddSystemd() integrate lifetime and logging with the service manager. See
Host on Linux with Nginx.
Containers
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish Shop.Web/Shop.Web.csproj -c Release -o /app
FROM mcr.microsoft.com/dotnet/aspnet:10.0-noble-chiseled AS final
WORKDIR /app
COPY --from=build /app .
USER $APP_UID
ENV ASPNETCORE_HTTP_PORTS=8080
EXPOSE 8080
ENTRYPOINT ["dotnet", "Shop.Web.dll"]
Chiseled / distroless runtime images are small and have no shell; run as non-root ($APP_UID). Deploy to
Azure App Service, Azure Container Apps, Kubernetes, or AWS (ECS/App Runner). See
Host ASP.NET Core in Docker containers.
Behind a proxy or load balancer
builder.Services.Configure<ForwardedHeadersOptions>(o =>
{
o.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
o.KnownNetworks.Clear();
o.KnownProxies.Clear(); // then add the actual proxy IPs/ranges
});
app.UseForwardedHeaders();
app.UsePathBase("/shop"); // if hosted under a sub-path
Production config, secrets, and CI/CD
-
Configuration from environment variables / Key Vault / managed identity; no secrets in the image or repo.
-
Expose readiness/liveness endpoints for the orchestrator’s probes (see Observability).
-
A web farm must share the Data Protection key ring and set the same application name (see Security hardening).
# .github/workflows/deploy.yml
name: deploy
on: { push: { branches: [main] } }
jobs:
build-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with: { dotnet-version: '10.0.x' }
- run: dotnet test --configuration Release
- run: dotnet publish Shop.Web -c Release -o publish
- uses: azure/webapps-deploy@v3
with: { app-name: shop-prod, package: publish }
Container build-and-deploy flow
App Service / Container Apps / K8s"] HOST --> PROBE["readiness probe passes -> receives traffic"]