Dockerizing a Windows Service (.NET)

Hi Guys,

I am new to Docker, and I would like to know if it is possible to “Dockerize” a Windows Service created in .NET. I have not been able to find a good tutorial on this, or an article that would somehow show me the step by step process on how to do it. I have several windows services I created, and I would like them to be in Docker-Container. Is this possible? Thanks in advance, guys!

A newbie,
Eldon B. Tenorio
Philippines

1 Like

I don’t think you can run classic .NET type windows service on a docker. Unless the code is running on .NET core, can it be run on docker.

1 Like

Hi @rohits,

Thank you very much. Yes, I have heard of .NET Core, but I haven’t tried it yet. From your own experience, have you tried “converting” classic windows services so that it will be .NET Core-capable? Been wanting to have my windows services run in Docker-Container. Thank you very much in advance!

Windows containers are only available in insiders build.
So if your .NET service cannot run on Linux it’s not yet possible.
As soon as windows containers will be installed by default we’ll support it (by the end of the year).

Hi @ebriney, thanks for your inputs. Yes, basically .NET windows services cannot run on linux, since they aren’t built to run for that OS. I hope there will be a solution for .NET windows services for Dockers in the near future. Thanks for your reply.

Hi Guys! I was able to run dotnet core and created a sample application using Mac.

You may follow the steps as detailed in this site:
https://www.microsoft.com/net/core#macos

Hope this helps.

Thank you everyone for spending time on my question!

If you ever had problems installing OpenSSL on mac, here is the link to resolve this issue:

stackoverflow.com/questions/38670295/brew-refusing-to-link-openssl

Screenshot above shows that dotnet core was able to run a sample application wrtten in C#.

Thanks!

Ultimately, I think that the best way to dockerize a long-running app (whether Docker or not) is to use Docker Swarm and create a service: https://docs.docker.com/engine/reference/commandline/service_create/

1 Like

Hi @friism, thank you very much! I am now going to read the site you just mentioned. Really much appreciated this!

Now Can we dockerize Window Services (.NET) ?

Hi,

I’m going to try and revive this thread because I’m pretty sure it’s possible now and I’m also interested in that answer.

I’m new to docker but from what I understand, in principle, you can now pull a Windows server/nanoserver image and build on top of it.
You can install your service using power shell and start it (or even plain old command line maybe)
I’m not sure how to send the stop signal to the service when the container stops.

Then I think you can really reuse your service as is and you don’t even need to migrate it to .net core, but you have to run the image on docker for Windows which requires Windows 10 pro or server 2016, to my knowledge.

If you want to be able to run your image on Linux, you’ll need to rewrite your code a bit to migrate to .net core, and build on top of the .net core image.

I haven’t tried it yet but I will when I find some time.

Cheers

Why not a console application instead?

Technically Windows service is a managed exe/console application. So why not a console application instead?

Docker requires the primary process of the container (the CMD or ENTRYPOINT, in Dockerfile terms) to be a normal executable, not a service. There are three things special about this process.

  1. The container stays up as long as this process is running.
  2. Environment variables for this process can be set by the docker engine, for example via -e switches of the docker create or docker run commands.
  3. The standard output and standard error of this process goes to the docker log.

Windows services are run under the control of the Windows Service Control Manager, which manages their lifetime. Therefore, they cannot be used as the primary process. However, Docker for Windows does allow you to install and run services in docker containers, as long as there is a primary process which keeps the container alive.

In the official Microsoft images microsoft/iis and microsoft/aspnet, a program called ServiceMonitor.exe is used as the primary process. This monitors the IIS service (w3svc) and stops itself (and therefore the container) when the service stops. In this way, it fulfils the first criterion in the list above. It also injects its own environment variables into the IIS process, thus fulfilling the second criterion. It does not try to fulfil the third. You can find the source code here. You can possibly adapt this.

However, this is not the perfect solution. Why do we create a Windows service? Probably because we want it to start without manual intervention, run as a different user, and sit in the background listening for requests. We can do all three using a container. But the container requires a regular executable.

So, I would probably begin by refactoring the actual functionality of your service into a separate class. Then, I would keep your Windows Service project (which should now have a Service class that uses your functionality class) for non-container use. And I would create a new console application, which uses the same functionality class, and use this console application as the ENTRYPOINT of a container.

2 Likes

The following Dockerfile works well for me in building a Windows Service into a docker image. All your service files need to be in the ‘Installs’ folder of the docker context, plus a copy of the InstallUtils.exe file (from .NET / Visual Studio).

# escape=\

FROM mcr.microsoft.com/dotnet/framework/aspnet:4.7.2-windowsservercore-1709

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

COPY ["Installs/", "/Service/"]

WORKDIR "C:/Service/"

RUN "C:/Service/InstallUtil.exe" /LogToConsole=true /ShowCallStack SmartFormsToWorkInjuryReportingService.exe; \
    Set-Service -Name "\"My Windows Service Name\"" -StartupType Automatic; \
    Set-ItemProperty "\"Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\My Windows Service Name\"" -Name AllowRemoteConnection -Value 1

ENTRYPOINT ["powershell"]
CMD Start-Service \""My Windows Service Name\""; \
    Get-EventLog -LogName System -After (Get-Date).AddHours(-1) | Format-List ;\
    $idx = (get-eventlog -LogName System -Newest 1).Index; \
    while ($true) \
    {; \
      start-sleep -Seconds 1; \
      $idx2  = (Get-EventLog -LogName System -newest 1).index; \
      get-eventlog -logname system -newest ($idx2 - $idx) |  sort index | Format-List; \
      $idx = $idx2; \
    }

FYI, you can then run the service by:

docker run --rm --net=MyNet --platform=windows -p 80:80 --name MyWindowsServiceContainer mywindowsserviceimage

Hi @andrewatactgov,
Thanks for your response. It is a great help.

FROM mcr.microsoft.com/dotnet/framework/runtime:4.7.2-windowsservercore-ltsc2019

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

COPY ["C:/Install/", "/Service/"]

WORKDIR "C:/Service/"

RUN "C:/Service/InstallUtil.exe" /LogToConsole=true /ShowCallStack AzureFilePushOnpremiseToCloud.exe; \
    Set-Service -Name "\"My Windows Service Name\"" -StartupType Automatic; \
    Set-ItemProperty "\"Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\My Windows Service Name\"" -Name AllowRemoteConnection -Value 1

# -StartupType Automatic; 

ENTRYPOINT ["powershell"] \
CMD Start-Service \""My Windows Service Name\""; \
    Get-EventLog -LogName System -After (Get-Date).AddHours(-1) | Format-List ;\
    $idx = (get-eventlog -LogName System -Newest 1).Index; \
    while ($true) \
    {; \
      start-sleep -Seconds 1; \
      $idx2  = (Get-EventLog -LogName System -newest 1).index; \
      get-eventlog -logname system -newest ($idx2 - $idx) |  sort index | Format-List; \
      $idx = $idx2; \
    }

I am getting this error; after deploying Windows Service:

The transacted install has completed.
Set-Service : Service My Windows Service Name was not found on computer ‘.’.
At line:1 char:172

  • … oCloud.exe; Set-Service -Name “My Windows Service Name” -StartupType …
  •             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : ObjectNotFound: (.:String) [Set-Service], Invali
      dOperationException
    • FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.C
      ommands.SetServiceCommand

And I am not clear how to run windows service once it deployed; it’s not clear from your command

docker run --rm --net=MyNet --platform=windows -p 80:80 --name MyWindowsServiceContainer mywindowsserviceimage

What is value of MyWindowsServiceContainer and mywindowsserviceimage

Thanks in advance

Hi, I have Dotnet framework app version 4.6.1 build .

How to Dockerize it on windows OS Machine. And also about Containerizing.

Please suggest a better way.

As we Researched we found few examples online and could not pull images like

FROM mcr.microsoft.com/windows/servercore:ltsc2016

But unfortunately not able to pull and run these instructions.

Hi, we are planning to migrate .Net application from VMware to Docker container,could you please suggest/help me out to move forward.

Hi,

what value did you pass for MyWindowsServiceContainer and mywindowsserviceimage

1 Like

Hi!

I use New-Service like “RUN New-Service -Name "\"My Windows Service Name"\" -BinaryPathName AzureFilePushOnpremiseToCloud.exe” instead of

More details: docs.microsoft.com

HI All,
I am using .net framework 4.7 . I created GRPC server using console application. but it does not run on container . i f i run it manually its working .
So how can i run it with container on kubarnetes window server?
Please help me!

Thanks
Himanshu