Starting a Windows service in a Docker container - docker

I am using Docker for Windows and am trying to convert a Asp.NET MVC 5 to a container. The one remaining roadblock is that I need the ASPNET State server running. I can start up the service through the interactive terminal and it works just fine, but am unable to get the container to start the service automatically. I've tried using CMD, ENTRYPOINT, and RUN, but from what I gather some of these will only execute the command while the image is building, not when the container starts.
My DOCKERFILE is as follows
FROM microsoft/aspnet:4.7.1-windowsservercore-1709
ARG source
WORKDIR /inetpub/wwwroot
COPY ${source:-obj/Docker/publish} .
CMD powershell -Command \
Set-Service aspnet_state automatic; \
Start-Service -name "aspnet_state"; \
EXPOSE 1433

Instead of using CMD, I used RUN to commit the command to the image, and used multiple RUN commands:
# Enable Session State Server
RUN powershell -Command Set-Service aspnet_state -startuptype automatic
RUN powershell -Command Stop-Service aspnet_state
RUN powershell -Command Start-Service aspnet_state
RUN powershell -Command Set-ItemProperty Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters -Name AllowRemoteConnection -Value 1

You simply need the following code after you have properly installed the service into the image.
ENTRYPOINT ["powershell"]
CMD Start-Service \""MyWindowsServiceName\"";
NOTE: The name of a windows service may be different to its executable name. You need the windows service name here, not the executable name.

Related

Starting Powershell Script on Container Startup in Azure App Service

I'm trying to use Azure App Service Containers to host Azure DevOps Pipeline agents. I've got everything working in the sense that my agent runs great locally using Docker Desktop, but when I publish the image to the App Service, the startup command is never executed. I'm forced to get a console in the container and manually run the powershell script, which then works as expected.
Here is my docker file:
FROM mcr.microsoft.com/windows/servercore:ltsc2019
RUN powershell Install-PackageProvider -Name NuGet -Force
RUN powershell Install-Module PowershellGet -Force
RUN powershell Install-Module -Name Az -Repository PSGallery -Force
RUN powershell Install-Module -Name Az.Tools.Migration -Repository PSGallery -Force
RUN powershell Enable-AzureRMAlias
WORKDIR /azp
COPY start.ps1 .
CMD powershell "c:\azp\start.ps1"
The deployment center logs show no errors. It's as if the CMD is never run.
please replace powershell CMD line as below -
CMD ["powershell.exe", "-File", "c:\azp\start.ps1"]
also its always good to use the full path for the exe if its not exist in PATH.
also use workdir as below -
FROM mcr.microsoft.com/windows/servercore:ltsc2019
RUN powershell Install-PackageProvider -Name NuGet -Force
RUN powershell Install-Module PowershellGet -Force
RUN powershell Install-Module -Name Az -Repository PSGallery -Force
RUN powershell Install-Module -Name Az.Tools.Migration -Repository PSGallery -Force
RUN powershell Enable-AzureRMAlias
WORKDIR c:\azp
COPY start.ps1 .
CMD ["powershell.exe", "-File", "c:\azp\start.ps1"]
I did not try building your docker image, but you should investigated on how ENTRYPOINT is defined, and so how it interacts with CMD.
Look at the Official Guide.
According to docker documentation, if you want a command to be always executed you must pass it in ENTRYPOINT and not in CMD.
When you pass your command in CMD, it can be overridden by an argument when the container is executed.
CMD will be overridden when running the container with alternative arguments.
So I don't know how you run your container but I advise you to try to pass your script in ENTRYPOINT.
Something like that:
FROM mcr.microsoft.com/windows/servercore:ltsc2019
RUN powershell Install-PackageProvider -Name NuGet -Force
RUN powershell Install-Module PowershellGet -Force
RUN powershell Install-Module -Name Az -Repository PSGallery -Force
RUN powershell Install-Module -Name Az.Tools.Migration -Repository PSGallery -Force
RUN powershell Enable-AzureRMAlias
WORKDIR c:\azp
COPY start.ps1 .
ENTRYPOINT ["powershell.exe", "c:\\azp\\start.ps1"]

Windows Docker Trying to run a service

I'm not sure where this is going wrong at all but I'm new to containers and trying to learn as I go.
I'm trying to containerize a windows service/application and expose a port via a container but can't quite tell how I investigate where it's failing.
I should point out that I'm running this on Server 2019 Datacentre inside VMWare Player.
Dockerfile:
# escape=`
FROM mcr.microsoft.com/windows/servercore:10.0.17763.2300-amd64
RUN powershell -Command `
Add-WindowsFeature Web-Server; `
Invoke-WebRequest -UseBasicParsing -Uri "https://dotnetbinaries.blob.core.windows.net/servicemonitor/2.0.1.10/ServiceMonitor.exe" -OutFile "C:\ServiceMonitor.exe"
EXPOSE 80
ENTRYPOINT ["C:\\ServiceMonitor.exe", "w3svc"]
COPY installer.exe ./
COPY service_start.ps1 ./
RUN powershell -Command `
Start-Process C:\\installer.exe -ArgumentList '-i -nomsg'` -Wait
CMD ["powershell.exe", "C:\\service_start.ps1"]
EXPOSE 1950
Now in theory, this docker file should create an IIS setup along with installing my service. IIS will run on port 80, my service will communicate on port 1950.
The service_start.ps1 contains:
Start-Service -Name "STO Controller"
which is the name of the service I'm installing (and works locally)
In PS, I run:
docker build -t STOBASE .
and the build process is successful.
I then run:
docker run -p 1000:80 -p 1001:1950 -dit STOBASE
This creates the container and I can see that the IIS portion forces it to stay active
docker ps a
shows that this is definitely running.
I open a browser and go to http://localhost:1000 and see the IIS splash screen so this part works
http://localhost:1001 should display the splash screen for the service.
MY first thought is that servercore is missing a dependancy as I don't know a lot about the service I'm installing other than it seems to have an integrated webserver due to the fact it serves up a webpage that is accessible on port 1950 from another machine.
Any ideas what I've missed or how I investigate this?

Unable to start container. Error message: Open Compute System failed

I am new to the containers and have created a Windows Docker image which is running fine locally as https://localhost but when I published the image on Docker Hub and tried to use in Web App Container its failing with the error message: Unable to start container. Error message: Open Compute System failed.
This is my Dockerfile
FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2019
ARG source
WORKDIR /inetpub/wwwroot
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]
RUN Install-WindowsFeature NET-Framework-45-ASPNET ; "\
Install-WindowsFeature Web-Asp-Net45; \
Invoke-WebRequest -UseBasicParsing -Uri "https://dotnetbinaries.blob.core.windows.net/servicemonitor/2.0.1.6/ServiceMonitor.exe" -OutFile "C:\ServiceMonitor.exe"
#Expose port 443 to allow incoming traffic over the default HTTPS port
EXPOSE 443
#create a folder on the container to hold the code
RUN powershell -Command \
New-Item -Path sampleaspnet -ItemType Directory
#Set the newly created folder in docker as the working directory for subsequent commands
WORKDIR 'C:\inetpub\wwwroot\sampleaspnet'
#Copy everything from where you are on host to the working directory in docker (this folder should contain your SSL cert)
COPY ./bin/Release/PublishOutput/ .
COPY IIS_Docker.pfx .
RUN powershell.exe -Command "\
Import-Module IISAdministration; \
Import-Module WebAdministration; \
Remove-Website -Name 'Default Web Site'; \
New-Website -Name 'sampleaspnet' -IPAddress '*' -Port 443 -PhysicalPath 'C:\inetpub\wwwroot\sampleaspnet' -ApplicationPool '.NET v4.5' -Ssl -SslFlags 0; \
#If you have a password on your SSL Cert, put it here as it needs "secured". If not, remove this line and the argument below it; \
$pwd = ConvertTo-SecureString -String 'admin123456' -Force -AsPlainText; \
#Import the certificate and store it in a variable to bind to later; \
$cert = Import-PfxCertificate -Exportable -FilePath 'IIS_Docker.pfx' -CertStoreLocation cert:\localMachine\My -Password $pwd; \
#Take the imported certificate and bind it to all traffic toward port 443 (you need to specify IP if you want multiple apps on 1 docker which I believe is ill-advised); \
New-Item -Path IIS:\SslBindings\0.0.0.0!443 -value $cert;"
Check the container logs but an Open Compute System Failed is could indicate a problem retrieving and running your image. There is a timeout for loading the image and mounting the backend storage.
Your docker file is doing a lot that's unnecessary though. Your base image is a cached image, which is good because that means images aren't being pulled from fresh. But mcr.microsoft.com/dotnet/framework/aspnet:4.8 already has IIS, .NET 4.5 (through .NET 4.8), and IIS extensibility. You don't need to expose 443 because the app service will bind a port on your image to route HTTP traffic as necessary. You also don't need to configure a SSL certificate as you'll configure that on the app service as well.
Have a look at this Dockerfile for how you can configure your image with your .NETFX application but I would start with the following:
EDIT: Here's my complete dockerfile.
# image for building our app
FROM mcr.microsoft.com/dotnet/framework/sdk:4.8 AS build
WORKDIR /app
# copy the project files
COPY *.sln .
COPY DemoForms.Web/*.csproj ./DemoForms.Web/
COPY DemoForms.Web/*.config ./DemoForms.Web/
RUN nuget restore
# build it
COPY DemoForms.Web/. ./DemoForms.Web/
WORKDIR /app/DemoForms.Web
RUN msbuild /p:Configuration=Debug
# and run it
FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2019 as runtime
WORKDIR /inetpub/wwwroot
COPY --from=build /app/DemoForms.Web/. ./

How can I run `powershell` command on mcr.microsoft.com/powershell container

My docker image is from mcr.microsoft.com/powershell:latest which has powershell installed. Why do I get this error when build docker image: /bin/sh: 1: Install-Module: not found
Below is my dockerfile:
FROM mcr.microsoft.com/powershell:latest
RUN Install-Module dbatools -Force
I can run the command Install-Module dbatools -Force when I manually launch a container from mcr.microsoft.com/powershell:latest. Why can't I run it from building the image? Does it have a different context? If it uses my localhost context, does it mean I need to install powershell on my Mac OS?
If I want to run a powershell script as ENTRYPOINT, how can I specify it?
you can use SHELL directive in Dockerfile:
escape=`
SHELL ["powershell","-command"]
RUN New-Item -ItemType Directory C:\Example
see more here

Invoke-WebRequest in docker Entrypoint

Docker file -
FROM microsoft/aspnet:4.6.2-windowsservercore-ltsc2016
WORKDIR /src
COPY ./install /src/install
ENTRYPOINT ["powershell.exe -ExecutionPolicy Bypass -NoProfile c:\\src\\install\\UpdateWindowsService.ps1;"]
CMD ["C:\\ServiceMonitor.exe", "w3svc"]
Powershell file
#Invoke-WebRequest -Uri $zipPath -OutFile $destFile
Write-Host "Downloaded File from $zipPath !" -ForegroundColor Yellow;
I need powershell file to run on startup so that it will download the latest zip file and further script will proceed with buisness logic But I am getting error while running the docker in container instance.
Error
Unable to connect remote server
Strangely When I access Docker using docker exec -it <container-id> powershell it downloads the zip successfully. Not able to understand where actual problem is.

Resources