Host your ASP.NET Core 2.2 Web App with IIS (in-process and out-of-process hosting model) and deploy to Docker Windows Containers

One of the new features of ASP.NET Core 2.2 is support for hosting ASP.NET Core Web App with IIS using in-process or out-of-process hosting model. This article will cover steps needed to

  • Host ASP.NET Core 2.2 Web API with IIS using in-process hosting model
  • Host ASP.NET Core 2.2 Web API with IIS using out-of-process hosting model
  • Host ASP.NET Core 2.2 Web API in Docker Windows containers (with IIS)

In ASP.NET Core 2.2, a new ASP.NET Core Module (AspNetCoreModuleV2) has been introduced which is a native IIS module that plugs into the IIS pipeline and provides in-process or out-of-process hosting capabilities. AspNetCoreModule used to be the module in previous version.

The dev tools used to develop these components are Visual Studio 2017 and Docker for Windows (Docker CE) and source code is available for download at GitHub.

ASP.NET Core 2.2 in-process hosting model with IIS

The main pointers about in-process hosting model with IIS are

  • This is the default hosting model on creating a new ASP.NET Core 2.2 app where ASP.NET Core app is hosted within IIS worker process (w3wp.exe).
  • When hosting in-process, ASP.NET Core module uses an in-process server implementation for IIS, called IIS HTTP Server (IISHttpServer) and avoids the additional cost of reverse-proxying requests over to a separate dotnet process.
  • You can specify in-process hosting model by
    • Editing project file i.e. <AspNetCoreHostingModel> InProcess </AspNetCoreHostingModel>
    • Navigate to Project Properties > Debug > Web Server Settings and choose Hosting Model (you need to select IIS Express profile)
  •  You need to use one app pool per app as sharing an app pool among apps isn’t supported.
  • The new module is only capable of hosting .NET Core in the IIS process.

A sample web.config on publishing ASP.NET Core 2.2 Web App using in-process hosting model is displayed below

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="dotnet" arguments=".\SampleWebAppForIIS.dll" stdoutLogEnabled="false"
                  stdoutLogFile=".\logs\stdout" hostingModel="InProcess" />
    </system.webServer>
  </location>
</configuration>

ASP.NET Core 2.2 out-of-process hosting model with IIS

The main pointers about out-of-process hosting model with IIS are

  • Kestrel Server is used instead of IISHttpServer. The ASP.NET Core module forwards requests to ASP.NET Core app running Kestrel Server.
  • When hosting out-of-process, the module only works with Kestrel. The module is incompatible with HTTP.sys.
  • You can specify out-of-process hosting model by
    • Editing project file i.e. <AspNetCoreHostingModel>OutOfProcess </AspNetCoreHostingModel>
    • Navigate to Project Properties > Debug > Web Server Settings and choose Hosting Model (you need to select IIS Express profile)
    • In case you do not specify AspNetCoreHostingModel in project file, it defaults to out-of-process hosting model.

A sample web.config on publishing ASP.NET Core 2.2 Web App using out-of-process hosting model is displayed below

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="dotnet" arguments=".\SampleWebAppForIIS.dll" stdoutLogEnabled="false"
                  stdoutLogFile=".\logs\stdout" hostingModel="OutOfProcess" />
    </system.webServer>
  </location>
</configuration>

Host ASP.NET Core 2.2 Web API in Docker Windows containers (with IIS)

Ensure that you have ASP.NET Core 2.2 installed on your developer machine. Create an ASP.NET Core Web App and select ASP.NET Core 2.2 version of .NET Core along with enabling Docker support (OS: Windows) as displayed below

I have updated the controller’s Get method to return the process name based on which we can identify in-process and out-of-process hosting model with IIS.

public ActionResult<ienumerable> Get()
{
return new string[] { Process.GetCurrentProcess().ProcessName };
}</ienumerable

Update the DockerFile as displayed below and main pointers about DockerFile are

  • I have specified microsoft/iis as base image since I need to deploy Web API to windows containers having IIS.
  • Dotnet 2.2.0 hosting pack needs to be installed as microsoft/iisimage doesn’t has ASP.NET Core 2.2 runtime installed which is needed to run the ASP.NET Core 2.2 Web App.
  • microsoft/dotnet:2.2-sdk-nanoserver-1803image is needed to build ASP.NET Core 2.2 Web Application project.
  • Docker multi-stage build optimizes image size by removing intermediate containers.
  • Instead of using Default Web Site, I have created a new app pool and a web site. App pool name is ‘ap-samplewebapp’ and web site name is ‘samplewebapp’.
  • Managed Runtime version of app pool is set to blank since ASP.NET Core runs in a separate process and manages the runtime. ASP.NET Core doesn’t rely on loading the desktop CLR. Setting the .NET CLR version to No Managed Code is optional.
  • In case you need Integrated Windows authentication, you will need Group Managed Service Accounts(gMSA). You can read further about gMSA @ Active Directory Service Accounts for Windows Containers

# escape=`
FROM microsoft/iis as base
## Install dotnet 2.2.0 hosting pack
SHELL ["powershell""-Command""$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue'; $verbosePreference='Continue';"]
ADD https://download.visualstudio.microsoft.com/download/pr/48adfc75-bce7-4621-ae7a-5f3c4cf4fc1f/9a8e07173697581a6ada4bf04c845a05/dotnet-hosting-2.2.0-win.exe "C:/setup/dotnet-hosting-2.2.0-win.exe"
RUN start-process -Filepath "C:/setup/dotnet-hosting-2.2.0-win.exe" -ArgumentList @('/install''/quiet''/norestart') -Wait 
RUN Remove-Item -Force "C:/setup/dotnet-hosting-2.2.0-win.exe"
## End Install dotnet 2.2.0 hosting pack

## Build and Publish Web App
FROM microsoft/dotnet:2.2-sdk-nanoserver-1803 AS build
WORKDIR /src
COPY ["SampleWebAppForIIS/SampleWebAppForIIS.csproj""SampleWebAppForIIS/"]
RUN dotnet restore "SampleWebAppForIIS/SampleWebAppForIIS.csproj"
COPY . .
WORKDIR "/src/SampleWebAppForIIS"
RUN dotnet build "SampleWebAppForIIS.csproj" --no-restore --no-dependencies -c Release -o /app 
FROM build AS publish
RUN dotnet publish "SampleWebAppForIIS.csproj" -c Release -o /publish
FROM base AS final
WORKDIR /inetpub/wwwroot/samplewebapp
## Create Web Site and Web Application
RUN Import-Module WebAdministration; `
    Remove-Website -Name 'Default Web Site'; `
    New-WebAppPool -Name 'ap-samplewebapp'; `
    Set-ItemProperty IIS:\AppPools\ap-samplewebapp -Name managedRuntimeVersion -Value ''; `
    Set-ItemProperty IIS:\AppPools\ap-samplewebapp -Name enable32BitAppOnWin64 -Value 0; `
    Set-ItemProperty IIS:\AppPools\ap-samplewebapp -Name processModel.identityType -Value Service; `
    New-Website -Name 'samplewebapp' `
                -Port 80 -PhysicalPath 'C:\inetpub\wwwroot\samplewebapp' `
                -ApplicationPool 'ap-samplewebapp' -force
COPY --from=publish /publish .
EXPOSE 80

Build and Publish Docker Image to Docker Hub

If you have Docker for Windows installed, you can run commands listed below to build and publish docker image to Docker Hub

  • Build Docker Image: docker build -t samplewebapp -f ./SampleWebApplicationforIIS/DockerFile .
  • Tag Docker Image: docker tag samplewebapp {YOUR_DOCKER_REPO}
  • Publish Image to Docker Hub: docker push {YOUR_DOCKER_REPO}

As an alternate option, you can also create Azure DevOps build pipeline to build and publish docker image to Docker Hub. The steps are

  • Specify ‘Docker Container’ template during creating build pipeline
  • Specify ‘Hosted Windows Container’ as Agent Pool
  • Select a Docker registry service connection
  • Specify DockerFile, Docker connection, Image Name etc. values in Build, Tag and Publish steps.

Create Windows Container from ASP.NET Core 2.2 Web API Docker image

After publishing Docker image, the next step is to create Windows container from ASP.NET Core 2.2 Web API Docker image. The Docker commands which are needed to create Windows container in ‘Docker for Windows’ are

  • Create Docker Windows container by executing command docker run -d -p 8000:80 --name samplewebappdemo {YOUR_DOCKER_REPO}. This command will also display Container ID upon completion.
  • Get the IP Address of the container by running command docker inspect -f "{{ .NetworkSettings.Networks.nat.IPAddress }}" samplewebappdemo. This address is needed to browse to Web API URL.
  • If you want to connect to a running container using powershell, the command is docker exec -t -i {YOUR_CONTAINER_ID} powershell

You can also install Kitematic which is used to manage Docker containers from GUI.

Demo

Navigate to the Web API URL after creating container(in-process), you will find that process name for in-process hosting model app is ‘w3wp’.

Similarly, if you navigate to the Web API URL after creating container (out-of-process), you will find that process name for out-of-process hosting model is ‘dotnet’.

Summary

This completes the article about hosting ASP.NET Core Web App with IIS using in-process or out-of-process hosting model along with deploying ASP.NET Core Web app to Windows Docker containers. You can download source code for this article from GitHub.

Leave a Reply

Your email address will not be published. Required fields are marked *