Как происходит развертывание приложения на IIS, Linux и Docker
Что проверяют
Знаете ли вы, как ASP.NET Core на самом деле запускается в каждой из трёх сред и чем они отличаются. Следом обычно спрашивают, что стоит перед Kestrel в проде и как приложение узнаёт настоящий адрес клиента за прокси.
Как отвечать
Общий шаг для всех вариантов: dotnet publish -c Release, сборка framework-dependent или self-contained. dotnet run в проде не используют, он собирает проект из исходников.
- IIS: на сервер ставится ASP.NET Core Hosting Bundle с модулем ANCM. Пул приложений в режиме «No Managed Code», учётке
IIS AppPool\<имя>выдаются права на папку.web.configсоздаёт публикация, хостинг по умолчанию in-process, внутриw3wp.exe. При выкладке кладутapp_offline.htm, чтобы IIS отпустил заблокированные DLL, или используют Web Deploy; - Linux: файлы в
/var/www/app, юнит systemd сExecStart=/usr/bin/dotnet /var/www/app/App.dll,Restart=alwaysиASPNETCORE_ENVIRONMENT=Production. Перед Kestrel ставят Nginx с TLS, а в приложении включаютUseForwardedHeaders, иначе оно видит только адрес прокси и не знает про HTTPS; - Docker: многоэтапный Dockerfile, сборка на
mcr.microsoft.com/dotnet/sdk, запуск наmcr.microsoft.com/dotnet/aspnetтой же версии. С .NET 8 образы слушают порт 8080, а не 80, и в них есть непривилегированный пользовательapp. Можно обойтись без Dockerfile:dotnet publish /t:PublishContainerсобирает образ средствами SDK.
Версию берите поддерживаемую: .NET 10 LTS или .NET 8, поддержка которого заканчивается в ноябре 2026. Образы 5.0 из старых инструкций давно без обновлений безопасности. Секреты передаются переменными окружения или из хранилища секретов, а не лежат в appsettings.json внутри образа.
Где спотыкаются
Запускают приложение через dotnet run или вручную в SSH-сессии, без systemd. После перезагрузки сервера сайт не поднимается.
Пишут -p 8080:80 по старой памяти, а приложение в образе .NET 8 и новее слушает 8080, и контейнер «не отвечает».
За Nginx забывают про заголовки X-Forwarded-*: получают бесконечный редирект на HTTPS и чужие IP в логах.