Unable to run docker IIS windows container - asp.net

I am new to docker and trying to run legacy .NET applications inside a windows container (using docker desktop). Here is my dockerfile
FROM mcr.microsoft.com/windows/servercore:ltsc2019
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]
RUN dism.exe /online /enable-feature /all /featurename:iis-webserver /NoRestart
#Configure IIS
RUN Import-Module WebAdministration;New-Item –Path IIS:\AppPools\CustomApppool
RUN C:\windows\system32\inetsrv\appcmd.exe set apppool /apppool.name:CustomApppool /processModel.identityType:SpecificUser /processModel.username:us\user1 /processModel.password:P##Ss
RUN Install-WindowsFeature Web-Windows-Auth;
RUN Install-WindowsFeature Web-IP-Security;
RUN Install-WindowsFeature NET-WCF-HTTP-Activation45;
RUN Install-WindowsFeature Web-Dyn-Compression;
RUN Install-WindowsFeature Web-Scripting-Tools;
RUN Install-WindowsFeature Web-AppInit;
RUN Install-WindowsFeature Web-Http-Redirect;
RUN Install-WindowsFeature Web-WebSockets;
# Update permissions on website folder
RUN icacls 'c:\inetpub\wwwroot' /Grant 'IUSR:(OI)(CI)(RX)'
RUN icacls 'c:\inetpub\wwwroot' /Grant 'IIS AppPool\DefaultAppPool:(OI)(CI)(RX)'
RUN icacls 'c:\inetpub\wwwroot' /Grant 'IIS AppPool\CustomApppool:(OI)(CI)(RX)'
#Copy website files from App host folder to container wwwroot folder
COPY Admin/ "c:/inetpub/wwwroot/Admin"
COPY Sade/ "c:/inetpub/wwwroot/Sade"
COPY Rater/ "c:/inetpub/wwwroot/Rater"
#Copy Service Monitor file
COPY ServiceMonitor.exe C:/
RUN New-WebApplication -Name Admin -Site 'Default Web Site' -PhysicalPath C:\inetpub\wwwroot\Admin -ApplicationPool CustomApppool;
RUN New-WebApplication -Name Sade -Site 'Default Web Site' -PhysicalPath C:\inetpub\wwwroot\Sade -ApplicationPool CustomApppool;
RUN New-WebApplication -Name Rater -Site 'Default Web Site' -PhysicalPath C:\inetpub\wwwroot\Rater -ApplicationPool CustomApppool;
#Authentication Settings
# Enable Directory browsing
RUN C:\Windows\system32\inetsrv\appcmd.exe set config 'Default Web Site' /section:system.webServer/directoryBrowse /enabled:'True'
# Enable anonymous authentication
RUN Set-WebConfigurationProperty -Filter '/system.webServer/security/authentication/anonymousAuthentication' -Location 'Default Web Site' -Name enabled -Value True;
# Enable basic authentication
#RUN Set-WebConfigurationProperty -Filter '/system.webServer/security/authentication/basicAuthentication' -Location 'Default Web Site' -Name enabled -Value True;
# Enable Windows authentication
RUN Set-WebConfigurationProperty -Filter '/system.webServer/security/authentication/windowsAuthentication' -Location 'Default Web Site' -Name Enabled -Value False;
RUN Restart-Service W3SVC
EXPOSE 80
ENTRYPOINT ['C:\ServiceMonitor.exe','w3svc']
I am able to build the image by running docker build -t demo/site
I am running this command to start the container docker run -p 8000:80 demo/site:latest but i am getting this error:
At line:1 char:35
+ $ErrorActionPreference = 'Stop'; ['C:\ServiceMonitor.exe','w3svc']
+ ~
Missing type name after '['.
At line:1 char:58
+ $ErrorActionPreference = 'Stop'; ['C:\ServiceMonitor.exe','w3svc']
+ ~
Missing argument in parameter list.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordEx
ception
+ FullyQualifiedErrorId : MissingTypename
Please, what am i missing? What do i need to do to get the container to start, and to be able to browse my website on localhost?

Replace your single quotes on the last line with double quotes.
Also try replacing ENTRYPOINT with CMD as well.

Related

Install windows feacture asp-net-45 failed in docker build windows server 2019 docker image

Running environment of docker: windows server 2019 standard installed by command below
Install-Module -Name DockerMsftProvider -Repository PSGallery -Force
Install-Package Docker -ProviderName DockerMsftProvider -Force
While building docker image of windows server 2019 with docker file below:
FROM mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
WORKDIR /ViniBeer
COPY . .
RUN PowerShell Install-WindowsFeature NET-Framework-45-ASPNET; Install-WindowsFeature Web-Asp-Net45; \
Import-Module WebAdministration; \
New-WebApplication "ViniBeer" -Site 'Default Web Site' -ApplicationPool "DefaultAppPool" -PhysicalPath "C:\ViniBeer"
exception thrown in console as below:
add-windowsfeature : The request to add or remove features on the specified
server failed.
Installation of one or more roles, role services, or features failed. Error:
0x800f0922
At line:1 char:1
+ add-windowsfeature web-asp-net45
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (#{Vhd=; Credent...Name=localh
ost}:PSObject) [Install-WindowsFeature], Exception
+ FullyQualifiedErrorId : DISMAPI_Error__Failed_To_Enable_Updates,Microsof
t.Windows.ServerManager.Commands.AddWindowsFeatureCommand
Running the same feature installation command in host is worked.
Trying different command like
add-windowsfeature web-asp-net45
is still not working.
Is there any command or opeartion to install this feature without exception or way to build the image successfully?

Running ASP.NET 4.6 application inside a docker container - Site always 404s

I've been attempting to get an ASP.NET 4.6 application to run inside a Windows Docker container and while getting IIS to run with the default website was fairly simple, trying to get my actual application to run is proving to be difficult. Whenever I attempt to load my application it returns a 404 file not found.
Some background: The application I'm trying to run has to be installed under 'Default Web Site' with both the application and a SharedContent application installed under IIS, where the SharedContent is also a sub-application under the main application.
This results in 3 calls install the application under IIS:
RUN ["powershell", "New-WebApplication -Name MvcCompaniesV2 -Site 'Default Web Site' -PhysicalPath C:/inetpub/wwwroot/MvcCompaniesV2 -ApplicationPool DefaultAppPool"]
RUN ["powershell", "New-WebApplication -Name SharedContent -Site 'Default Web Site' -PhysicalPath C:/inetpub/wwwroot/SharedContent -ApplicationPool DefaultAppPool"]
RUN ["powershell", "New-WebApplication -Name MvcCompaniesV2/SharedContent -Site 'Default Web Site' -PhysicalPath C:/inetpub/wwwroot/SharedContent -ApplicationPool DefaultAppPool"]
After fiddling around for about a full day I'm confused. I managed to install IIS WebManagement and can connect to my container using the IIS Manager and I can see my websites are properly configured with one exception: the connection strings and rewrite rules from the web.config aren't visible from the IIS settings, like it can't access the config file. IIS runs under the IIS APPPOOL\DefaultAppPool user and the wwwroot folder has IIS_IUSRS added to its ACL(as by default).
This is my docker file:
FROM microsoft/aspnet:4.7.2-windowsservercore-1803
EXPOSE 80
EXPOSE 8172
EXPOSE 4020 4021 4022 4023
# WebManagement stuff
RUN ["powershell.exe", "Install-WindowsFeature NET-Framework-45-ASPNET"]
RUN ["powershell.exe", "Install-WindowsFeature Web-Asp-Net45"]
RUN ["powershell.exe", "Install-WindowsFeature web-mgmt-service"]
RUN ["powershell.exe", "Set-ItemProperty -Path 'HKLM:/SOFTWARE/Microsoft/WebManagement/Server' -Name 'EnableRemoteManagement' -Value 1"]
RUN ["powershell.exe", "set-service -Name WMSVC -StartupType Automatic"]
RUN ["powershell", "start-service WMSVC"]
RUN ["powershell", "net user patrick l0lp#ssw0rd /add"]
RUN ["powershell", "net localgroup administrators patrick /add"]
# Rewrite module
ADD https://download.microsoft.com/download/C/9/E/C9E8180D-4E51-40A6-A9BF-776990D8BCA9/rewrite_amd64.msi rewrite_amd64.msi
RUN ["powershell" , "Start-Process msiexec.exe -ArgumentList '/i', 'rewrite_amd64.msi', '/quiet', '/norestart' -NoNewWindow -Wait"]
# Remote debugger
RUN Invoke-WebRequest -OutFile c:\rtools_setup_x64.exe -Uri https://aka.ms/vs/15/release/RemoteTools.amd64ret.enu.exe;
RUN & 'c:\rtools_setup_x64.exe' /install /quiet
ADD bin C:/inetpub/wwwroot/
RUN ["powershell", "New-WebApplication -Name MvcCompaniesV2 -Site 'Default Web Site' -PhysicalPath C:/inetpub/wwwroot/MvcCompaniesV2 -ApplicationPool DefaultAppPool"]
RUN ["powershell", "New-WebApplication -Name SharedContent -Site 'Default Web Site' -PhysicalPath C:/inetpub/wwwroot/SharedContent -ApplicationPool DefaultAppPool"]
RUN ["powershell", "New-WebApplication -Name MvcCompaniesV2/SharedContent -Site 'Default Web Site' -PhysicalPath C:/inetpub/wwwroot/SharedContent -ApplicationPool DefaultAppPool"]
# ErrorPages mode to off
RUN ["powershell", "Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT' -filter 'system.web/customErrors' -name 'mode' -value 'Off'"]
RUN ["powershell", "Set-WebConfigurationProperty -filter 'system.webServer/httpErrors' -name 'errorMode' -value 'Detailed'"]
RUN ["Powershell", "Set-WebConfigurationProperty -pspath 'IIS:\Sites\Default Web Site\MvcCompaniesV2' -filter 'system.webServer/httpErrors' -name 'errorMode' -value 'Detailed'"]
ENTRYPOINT ["powershell", ""]
Any ideas on how I can troubleshoot this? As can be seen, I changed the errorPages mode for both IIS and .NET to detailed but whenever I open MvcCompaniesV2, I still get the very limited error page (https://imgur.com/a/jvj9r7f). I'm kind of out of ideas what I can try to troubleshoot this.
I tried a sample asp.net page(which runs directly under 'Default Web Site' and that works fine out of the box').
EDIT: When I attach the remote debugger to my project it breaks with an ArgumentException inside the framework code:
System.ArgumentException
HResult=0x80070057
Message=The parameter 'C:/inetpub/wwwroot/MvcCompaniesV2\' is invalid.
Parameter name: C:/inetpub/wwwroot/MvcCompaniesV2\
I fixed this problem by fixing the malformed 'PhysicalPath's from the New-WebApplication calls. The debugger's ArgumentException gave it away, IIS doesn't tolerate / in the paths. After updating them to C:\\inetpub\\wwwroot\\MvcCompaniesV2 the problem went away.

Docker - Windows IIS image - 'Remove-Website' is not recognized as an internal or external command,

I am trying to run my ASP.NET Web API on a docker container on Windows 2016 server. Here is my docker file:
FROM microsoft/dotnet-framework:4.7.2-sdk AS build
WORKDIR /app
# copy csproj and restore as distinct layers
COPY *.sln .
COPY TestWebAPI/*.csproj ./TestWebAPI/
COPY TestWebAPI/*.config ./TestWebAPI/
RUN nuget restore
# copy everything else and build app
COPY TestWebAPI/. ./TestWebAPI/
WORKDIR /app/TestWebAPI
RUN msbuild /p:Configuration=Release
FROM microsoft/iis:10.0.14393.206
RUN Remove-Website -Name 'Default Web Site'
RUN New-Website -Name 'TestWebApi' -Port 80 \
-PhysicalPath 'c:\app\TestWebAPI\' -ApplicationPool '.NET v4.5'
EXPOSE 80
CMD Write-Host IIS Started... ; \
while ($true) { Start-Sleep -Seconds 3600 }
I am using following commands to build the app:
docker image build --tag v2 --file .\Dockerfile .
After running the script, I am getting following error:
'Remove-Website' is not recognized as an internal or external command
I have seen few people using this command. What is the issue here?
Adding SHELL ["powershell"] fixed the issue.
FROM microsoft/dotnet-framework:4.7.2-sdk AS build
WORKDIR /app
# copy csproj and restore as distinct layers
COPY *.sln .
COPY TestWebAPI/*.csproj ./TestWebAPI/
COPY TestWebAPI/*.config ./TestWebAPI/
RUN nuget restore
# copy everything else and build app
COPY TestWebAPI/. ./TestWebAPI/
WORKDIR /app/TestWebAPI
RUN msbuild /p:Configuration=Release
FROM microsoft/iis:10.0.14393.206
SHELL ["powershell"]
COPY --from=build /app/TestWebAPI/. ./
RUN Remove-Website -Name 'Default Web Site'
RUN New-Website -Name 'TestWebApi' -Port 80 \
-PhysicalPath 'c:\appp\TestWebAPI\' -ApplicationPool '.NET v4.5'
EXPOSE 80
CMD Write-Host IIS Started... ; \
while ($true) { Start-Sleep -Seconds 3600 }

Publish ASP.Net site on Docker using MsDeploy

We are using MsDeploy for deploying our site on IIS. When we publish we get three files, viz.
MySite.deploy.cmd,
MySite.SetParameters.xml
MySite.zip.
And we run a command like;
MySite.cmd /Y /M:https://IpOfMachine/MsDeploy.axd
to deploy on the server.
Now we want to move it to docker, with docker file something like this -
FROM microsoft/iis
RUN powershell -NoProfile -Command Remove-Item -Recurse
C:\inetpub\wwwroot*
WORKDIR C:/DeploymentFiles
COPY DeploymentPackage/ .
RUN cmd MySite.cmd /Y /M:https://IpOfDockerInstance/MsDeploy.axd
But the MsDeploy thing is not working and giving 404 error. I think I need to add WebDepoly to get this working, but how to do it in Docker?
Any suggestions, please. I am a novice to Docker
It could be difficult to get started with docker, if one's is not through well with the basics. I spent some time in reading out more on it and finally come up with the following Docker file that worked for me. I have tired to document the script inline with a couple of references that helped me.
FROM microsoft/iis
#Keep the artifacts related for image in the same folder from where docker is running
RUN cmd mkdir C:/DeploymentFiles
WORKDIR C:/DeploymentFiles
# Copy and install msdeploy service
COPY WebDeploy_amd64_en-US.msi .
RUN msiexec /i WebDeploy_amd64_en-US.msi AGREETOLICENSE=yes ADDLOCAL=ALL /qn
RUN powershell Start-service MsDepSvc;
#Remove default iis site's contents
RUN powershell -NoProfile -Command Remove-Item -Recurse C:\inetpub\wwwroot\*
# Resolving 403 issue. Ref - https://github.com/microsoft/iis-docker/issues/5
#Adding a user so i can connect trough IIS Manager
RUN NET USER testing "Password01!" /ADD
RUN NET LOCALGROUP "Administrators" "testing" /add
#Grant Permissions
RUN icacls "C:\inetpub\wwwroot\*" /grant everyone:(OI)(CI)F /T
#Install neccassary features
RUN powershell Install-WindowsFeature Web-Mgmt-Service
RUN powershell Install-WindowsFeature Web-Windows-Auth
RUN powershell Install-WindowsFeature NET-Framework-45-ASPNET
RUN powershell Install-WindowsFeature Web-Asp-Net45
RUN powershell Install-WindowsFeature NET-WCF-HTTP-Activation45
#Start Service and make it autorun
RUN net start wmsvc
RUN sc config WMSVC start= auto
RUN powershell -NoProfile -Command \
Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\WebManagement\Server -Name EnableRemoteManagement -Value 1
# Copy deployment packages and related files to container to "C:/DeploymentFiles"
COPY DeployPackage/ .
# The Deploy_App.bat file contains the command to deploy using msdeploy
COPY Deploy_App.bat .
RUN C:/DeploymentFiles/Deploy_App.bat
# Resolve the ACL issues during deployment. Ref - https://fluentbytes.com/how-to-fix-error-this-access-control-list-is-not-in-canonical-form-and-therefore-cannot-be-modified-error-count-1/
COPY aclFix.ps1 .
RUN powershell.exe -executionpolicy bypass .\aclFix.ps1
RUN C:/DeploymentFiles/Deploy_App.bat
EXPOSE 80

Powershell scripting creation of a "sub" website

I have two folders:
c:\inetpub\site1
c:\inetpub\site1Sub
I want "site1" to be the "parent" website and "site1Sub" to be a "sub" website. Both sites should run under the same application pool, which is a custom pool created solely for these sites, call it "site1." In IIS Manager (7.5), I simply create the application pool, then the parent site, then right-click on the parent site and "Add Application," pointing it at the physical path "c:\inetpub\site1Sub." This all works fine.
When I try to script this in Powershell, however, things get difficult. I can create "site1" and the application pool with no problems. It's the sub-site that's being a pain. I've tried two approaches:
Approach 1: Use New-Item and set the app pool after.
$subSite = New-Item "IIS:\Sites\site1\site1Sub" -physicalPath "C:\inetpub\site1Sub" -type "Application"
$subSite | Set-ItemProperty -Name "applicationPool" -Value "site1"
With this approach, I receive an error after the Set-ItemProperty command:
Set-ItemProperty : Cannot find path 'C:\site1Sub' because it does not exist.
At line:1 char:127
+ $subSite | Set-ItemProperty -Name "applicationPool" -Value "site1" ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\site1Sub:String) [Set-ItemProperty], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetItemPropertyCommand
Approach 2: Create a virtual directory and use ConvertTo-WebApplication (as in this answer).
New-WebVirtualDirectory -Site "site1" -Name "site1Sub" -PhysicalPath "c:\inetpub\site1Sub"
ConvertTo-WebApplication -ApplicationPool "site1" "IIS:\Sites\site1\site1Sub"
This runs fine, and further, it looks fine in IIS Manager, but when I attempt to navigate to the site I receive an error stating that the web.config failed to parse:
It is an error to use a section registered as
allowDefinition='MachineToApplication' beyond application level. This
error can be caused by a virtual directory not being configured as an
application in IIS.
I'm totally stumped. How can I script this scenario in Powershell?
I've found that when creating an application under a website, I've needed to specify the -Force switch in the call to New-Item. I've left out the checking to see if the site already exists (Sneijder's answer shows how to do that with Test-Path), but this should do the trick:
Import-Module WebAdministration
$sitePath = 'IIS:\Sites\site1'
$subSitePath = "$sitePath\site1Sub"
$appPoolName = 'site1'
# Create Site and Subsite
New-Item $sitePath -PhysicalPath 'C:\Inetpub\site1' -Bindings #{protocol="http";bindingInformation=":80:"} }
New-Item $subSitePath -Type Application -PhysicalPath 'C:\Inetpub\site1Sub' -Force
# Create App Pool
New-Item "IIS:\AppPools\$appPoolName"
# Associate sites to App Pool
Set-ItemProperty $sitePath -Name applicationPool -Value $appPoolName
Set-ItemProperty $subSitePath -Name applicationPool -Value $appPoolName
As i understand you correctly, you would like to have following result in your local IIS Manager:
This script creates an application pool. Then it creates the root site and afterwards the subsite.
Import-Module WebAdministration
$iisAppPoolName = "applicationPool"
$iisAppPoolDotNetVersion = "v4.0"
$iisAppName = "site1"
$directoryPath = "C:\inetpub\site1"
$iisSubAppName = "site1sub"
$directorySubPath = "C:\inetpub\site1Sub"
#navigate to the app pools root
cd IIS:\AppPools\
#check if the app pool exists
if (!(Test-Path $iisAppPoolName -pathType container))
{
#create the app pool
$appPool = New-Item $iisAppPoolName
$appPool | Set-ItemProperty -Name "managedRuntimeVersion" -Value $iisAppPoolDotNetVersion
}
#navigate to the sites root
cd IIS:\Sites\
#check if the site exists
if (Test-Path $iisAppName -pathType container)
{
return
}
#create the site
$iisApp = New-Item $iisAppName -bindings #{protocol="http";bindingInformation=":80:"} -physicalPath $directoryPath
$iisApp | Set-ItemProperty -Name $iisAppPoolName -Value $iisAppPoolName
#create the subSite
$iisSubApp = New-WebApplication -Name $iisSubAppName -Site $iisAppName -PhysicalPath $directorySubPath -ApplicationPool $iisAppPoolName
Result:
Hope this helps.
Have you tried mapping your IIS directory tree as a PSDrive, then re-attempt approach 1?
https://technet.microsoft.com/en-us/library/ee176915.aspx
Do a Get-PSDrive to see what PS Providers are available to the host, then attempt to map it like a filesystem.
# For psprovider, I'm not sure if the provider name is 'IIS' or some other.
# For mapping remote drives, usually FileSystem works,
# but try Get-PSDrive to see whats available to your host for this switch.
New-PSDrive -name X -psprovider IIS -root 'IIS:\'
I don't have IIS config'd on my testbox to confirm for you, but just putting this up here to try.

Resources