microsoft / iis-docker

Dockerfile for IIS
https://hub.docker.com/r/microsoft/iis/
MIT License
293 stars 129 forks source link

Adding Cmd.exe at end of docker image results in IIS terminating #154

Closed alburgin closed 7 months ago

alburgin commented 5 years ago

We want to do some run time configuration on container startup. I have a docker file which consumes the ASP.Net base image and then runs the run time (not build time) configuration using a CMD. (Right now it just does an unzip but later it will do more.) When I add the line to do the run time configuration, I get the following failures: "Service 'w3svc' has been stopped

APPCMD failed with error code 4312

Failed to update IIS configuration"

Docker file contents - I have removed some stuff from the docker file which appears to be working:

FROM mcr.microsoft.com/dotnet/framework/aspnet:4.7.2-windowsservercore-ltsc2019 SHELL ["cmd", "/S", "/C"] COPY ${source}/ServiceRoot.zip C:/ServiceRoot.zip

TODO - add more run time config on top of the unzip.

CMD powershell.exe -command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('C:\ServiceRoot.zip', 'C:\ServiceRoot'); }"

crossan007 commented 5 years ago

I'm seeing the same thing..

Using an image build from this Dockerfile,

FROM mcr.microsoft.com/dotnet/framework/aspnet:4.7.2-windowsservercore-ltsc2019
ADD ./ApplicationBinaries /inetpub/wwwroot
ADD ./web.config /inetpub/wwwroot/web.config

COPY AppFirstRun.ps1 .

CMD ["powershell.exe", "-file C:\AppFirstRun.ps1"]

My containers constantly restart with this:

 Service 'w3svc' has been stopped

APPCMD failed with error code 4312

Failed to update IIS configuration
crossan007 commented 5 years ago

I'm testing out a theory now - I wonder if there's a race condition occurring on web.config.

Presumably your ServiceRoot.zip is touching/updating web.config. My .ps1 script is certainly adjusting the web.config (according to Docker Environment Variables).

Maybe "waiting" until IIS is settled before altering web.config would help.

crossan007 commented 5 years ago

This looks to be the same as: https://github.com/Microsoft/IIS.ServiceMonitor/issues/47 https://github.com/Microsoft/iis-docker/issues/47 https://github.com/Microsoft/IIS.ServiceMonitor/issues/38 https://github.com/Microsoft/IIS.ServiceMonitor/pull/31 https://github.com/Microsoft/IIS.ServiceMonitor/issues/4 https://github.com/Microsoft/IIS.ServiceMonitor/issues/16

WolfMessing commented 5 years ago

Hi, I had the similar issue. I guess it happened because of ServiceMonitor entrypoint in aspnet image. Try to use FROM mcr.microsoft.com/windows/servercore:ltsc2019 instead of aspnet image, then manually isntall net framework and enable web server, so your dockerfile should be like this:

FROM mcr.microsoft.com/windows/servercore:ltsc2019
SHELL ["powershell"]

RUN Add-WindowsFeature Web-Server; \
    Add-WindowsFeature NET-Framework-45-ASPNET; \
    Add-WindowsFeature Web-Asp-Net45

ADD ./ApplicationBinaries /inetpub/wwwroot
ADD ./web.config /inetpub/wwwroot/web.config

COPY AppFirstRun.ps1 .

CMD ["powershell.exe", "-file C:\AppFirstRun.ps1"]

RUN Invoke-WebRequest -UseBasicParsing -Uri "https://dotnetbinaries.blob.core.windows.net/servicemonitor/2.0.1.6/ServiceMonitor.exe" -OutFile "C:\ServiceMonitor.exe"

CMD ["C:\\ServiceMonitor.exe", "w3svc"]
crossan007 commented 5 years ago

@WolfMessing no success for me with the "multiple CMD" approach; Also, it looks like Dockerfile only allows one CMD entry.

WolfMessing commented 5 years ago

@crossan007 yes, you are right, I forgot that you already have it, try to delete last 2 lines

subbunori commented 5 years ago

I was able to workaround this by adding the servicemonitor w3svc part in a ps1 file and then call it via entrypoint. It is an override of entrypoint from aspnet image. (without [] syntax)

DockerFile snippet

COPY ./DockerInit/ /DockerInit
ENTRYPOINT ./DockerInit/ContainerRunTime.ps1

ContainerRunTime.ps1

###start application/host initialization logic
Write-Output "Setting Environment Variable"
[Environment]::SetEnvironmentVariable("TestVariableName", "TestValue", "Machine")
###end application/host initialization logic

### do not remove this block, this is the entrypoint that starts iis on the container
Write-Output "Starting ServiceMonitor.exe"
C:\\ServiceMonitor.exe w3svc
### do not remove this block, this is the entrypoint that starts iis on the container
ghost commented 5 years ago

I've been fighting with this for a while i've been unable to get any of the solutions to work until.. Part of my IIS install scrip is removing the default app pool and site. Once I removed this step subbunori's solution works.

Get-WebSite -Name "Default Web Site" | Remove-WebSite -Confirm:$false -Verbose ; Remove-WebAppPool -Name "DefaultAppPool" -Confirm:$false -Verbose ;

subbunori commented 5 years ago

If I am not overriding entrypoint from aspnet image, it is failing. Rerunning C:\ServiceMonitor.exe w3svc makes the container crash. This is a repro even after running this command from inside the container. Curious to know if this is a known issue and being fixed.

alburgin commented 5 years ago

I have figured this out. ServiceMonitor.exe has logic inside of it that checks to see if the default app pool is running and if not exit. Since it is the entrypoint by default in the image, it has to stay running to keep the container alive. If you wanted to override this behavior you would need to write your own entrypoint process that stays alive, and start that as the entrypoint instead.

subbunori commented 5 years ago

Thanks @alburgin. Exactly what I have done with below. ENTRYPOINT ./DockerInit/ContainerRunTime.ps1

Christoph2020 commented 5 years ago

So basically:

When trying to execute any type of script via CMD:

CMD ["powershell", "./somepsscript.ps1;"] 

I also get the "Service 'w3svc' has been stopped" message.

When trying to override ENTRYPOINT with my script the ServiceMonitor does not start anymore:

ENTRYPOINT ["powershell", "./somepsscript.ps1;"]

However, when I override ENTRYPOINT with my script and add the ServiceMonitor as a CMD it works.

ENTRYPOINT ["powershell", "./somepsscript.ps1;"] 
CMD ["C:\\ServiceMonitor.exe", "w3svc"]

Is there no better way to handle this?

ravikr-dev commented 5 years ago

I tried using ENTRYPOINT ./DockerInit/ContainerRunTime.ps1, I am setting environment variable at Machine level, but it does not set the variable in my case i.e.

When I try to get the environment variable, it throws me below error: Get-Variable : Cannot find a variable with the name 'Monitoring'.

But when I set the Environment variable to the container via powershell, and trying to start the ServiceMonitor.exe it does not start the container. C:\ServiceMonitor.exe w3svc

I tried multiple things but setting environment variable did not work for me. Any suggestions?

bestickley commented 4 years ago

I was able to get this working with the start.ps1 script:

pm2 start ecosystem.config.js
C:\ServiceMonitor.exe w3svc
el-veee commented 3 years ago

Just want to say @WolfMessing solution worked for me, both locally and running ECS container services. Thank you very much