Skip to content

Instantly share code, notes, and snippets.

@artisticcheese
Last active June 2, 2021 13:03
Show Gist options
  • Save artisticcheese/e4776f420f1d0088d87335284b103cce to your computer and use it in GitHub Desktop.
Save artisticcheese/e4776f420f1d0088d87335284b103cce to your computer and use it in GitHub Desktop.
Dockerfile to build IIS + nanoserver + ASP.NET core
# escape=`
# Image with NET CORE installation to extract executables for final image
FROM microsoft/aspnetcore:2.0.0-nanoserver As CoreBuild
# Middleware image used to extract ASP.NET core module
From microsoft/iis as WindowsBuild
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue'; $verbosePreference='Continue';"]
# Installing NET CORE webhosting in middleware image so latest module and configuration schema is extracted for final image
ADD https://download.microsoft.com/download/B/1/D/B1D7D5BF-3920-47AA-94BD-7A6E48822F18/DotNetCore.2.0.0-WindowsHosting.exe ".\hosting.exe"
RUN start-process -Filepath .\hosting.exe -ArgumentList @('/install', '/quiet', '/norestart') -Wait
FROM microsoft/iis:nanoserver
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue'; $verbosePreference='Continue';"]
RUN start-process -Filepath dism.exe -ArgumentList @('/online', '/enable-feature:IIS-WindowsAuthentication', '/ALL') -Wait
# Adding NET CORE EXE to Path environment variable
RUN setx /M PATH $($Env:PATH + ';' + $Env:ProgramFiles + '\dotnet')
#Copy dotnet core installation from middleware image
COPY --from=CoreBuild ["c:\\Program Files\\dotnet", "c:\\program files\\dotnet"]
#Copy dotnet core module from middleware image
COPY --from=WindowsBuild ["c:\\Windows\\System32\\inetsrv\\aspnetcore.dll", "c:\\Windows\\System32\\inetsrv\\"]
COPY --from=WindowsBuild ["c:\\Windows\\System32\\inetsrv\\config\\schema\\aspnetcore_schema.xml", "c:\\Windows\\System32\\inetsrv\\config\\schema\\"]
# Configure IIS to use ASPNET core module
RUN Import-Module IISAdministration; `
Start-IISCommitDelay; `
(Get-IISServerManager).GetApplicationHostConfiguration().RootSectionGroup.Sections.Add('appSettings') ; `
(Get-IISServerManager).GetApplicationHostConfiguration().GetSection('system.webServer/handlers').Overridemode = 'Allow' ; `
(Get-IISServerManager).GetApplicationHostConfiguration().RootSectionGroup.SectionGroups['system.webServer'].Sections.Add('aspNetCore'); `
(Get-IISServerManager).GetApplicationHostConfiguration().RootSectionGroup.SectionGroups['system.webServer'].Sections['aspNetCore'].OverrideModeDefault = 'Allow'; `
New-IISConfigCollectionElement (Get-IISConfigSection 'system.webServer/globalModules' | Get-IISConfigCollection) -ConfigAttribute @{'name'='AspNetCoreModule';'image'='C:\windows\system32\inetsrv\aspnetcore.dll'}; `
New-IISConfigCollectionElement (Get-IISConfigSection 'system.webServer/modules' | Get-IISConfigCollection) -ConfigAttribute @{'name'='AspNetCoreModule'}; `
Stop-IISCommitDelay
EXPOSE 80
@michha
Copy link

michha commented Apr 4, 2018

Thx for this code. It helped us achieving a similar goal and I want to share some comments:

@khanyuriy
Copy link

@michha hi! Thanks for comment, now i have iis calling my asp.net core app successfully. But still no windows auth.
This image works well "docker run -d -p 8080:80 -h containerhost --security-opt "credentialspec=file://win.json" artisticcheese/winauth:servercore", so gMSA works.
Can you point me some directions to chek, to get win auth running?
Also how did you know the hosting bundle url changed? How did you come up with Line4 and Line10 comments ?
Thanks!

@szahn
Copy link

szahn commented Jul 10, 2018

Why doesn't Microsoft provide an image with Asp.Net Core on IIS?

Updated it for Windows Server 1803 and Asp.Net Core 2.1.1

# escape=`
FROM microsoft/dotnet:2.1.1-aspnetcore-runtime-nanoserver-1803 as CoreBuild

FROM microsoft/iis as WindowsBuild
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue'; $verbosePreference='Continue';"]
ADD https://download.microsoft.com/download/9/3/E/93ED35C8-57B9-4D50-AE32-0330111B38E8/dotnet-hosting-2.1.1-win.exe ".\dotnet-hosting.exe"
RUN start-process -Filepath .\dotnet-hosting.exe -ArgumentList @('/install', '/quiet', '/norestart') -Wait 

FROM microsoft/iis:windowsservercore-1803
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue'; $verbosePreference='Continue';"]
RUN setx /M PATH $($Env:PATH + ';' + $Env:ProgramFiles + '\dotnet')
COPY --from=CoreBuild ["c:\\Program Files\\dotnet", "c:\\program files\\dotnet"]

#Copy dotnet core module from middleware image

COPY --from=WindowsBuild ["c:\\Windows\\System32\\inetsrv\\aspnetcore.dll", "c:\\Windows\\System32\\inetsrv\\"]
COPY --from=WindowsBuild ["c:\\Windows\\System32\\inetsrv\\config\\schema\\aspnetcore_schema.xml",  "c:\\Windows\\System32\\inetsrv\\config\\schema\\"]

COPY ./RegisterAspNetCoreHostIISModule.ps1 ./RegisterAspNetCoreHostIISModule.ps1

RegisterAspNetCoreHostIISModule.ps1:

Import-Module IISAdministration;
Start-IISCommitDelay;
(Get-IISServerManager).GetApplicationHostConfiguration().GetSection('system.webServer/handlers').Overridemode = 'Allow' ;
(Get-IISServerManager).GetApplicationHostConfiguration().RootSectionGroup.SectionGroups['system.webServer'].Sections.Add('aspNetCore');
(Get-IISServerManager).GetApplicationHostConfiguration().RootSectionGroup.SectionGroups['system.webServer'].Sections['aspNetCore'].OverrideModeDefault = 'Allow';
New-IISConfigCollectionElement (Get-IISConfigSection 'system.webServer/globalModules' | Get-IISConfigCollection) -ConfigAttribute @{'name'='AspNetCoreModule';'image'='C:\windows\system32\inetsrv\aspnetcore.dll'};
New-IISConfigCollectionElement (Get-IISConfigSection 'system.webServer/modules' | Get-IISConfigCollection) -ConfigAttribute @{'name'='AspNetCoreModule'};
Stop-IISCommitDelay

Having an issue with the last section where it updates the application config. Docker throws "APPCMD failed with error code 183 Failed to update IIS configuration" on start up. Ideally, the Powershell needs to check if the "appSettings" config section already exists before adding it. So for now, I put the script in a separate file which can be called at-will.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment