chemakchaou
chemakchaou

Reputation: 171

Dockerizing a Windows Service

I am new to docker and I have an application including a set of windows services (.NET). I d like to run it into a docker container. What should I do ?

Upvotes: 14

Views: 21503

Answers (3)

Vlad Stefan
Vlad Stefan

Reputation: 41

Starting from the answer provided by QA Collective, this is what worked for me.

Note 1 No InstallUtil.exe required

Note 2 the "Get-Event..." part from the last part of the code is just to keep the process alive so that the container will continue to run.

Note 3 You can set the StartupType as automatic and remove the Start-Service from the CMD.

Note 4 When you provide the BinaryPathName Make sure to provide the FULL PATH. It stores it in the registries and if you provide a relative path, it won't know where to run it from and you'd get some nasty errors that will make you cry - what happened to me.

FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2019


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

COPY ["Release/", "/Service/"]

WORKDIR "C:/Service/"
RUN New-Service -Name "\"MyService"\"  -StartupType "\"Manual"\"  -BinaryPathName "\"C:\\Service\\MyService.exe"\";



ENTRYPOINT ["powershell"]
cmd Start-Service "MyService"; \
    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; \
    }

Upvotes: 4

QA Collective
QA Collective

Reputation: 2439

I have successfully put a Windows Service into a docker container using the following Dockerfile. Replace MyWindowsServiceName with the name of your own windows service.

# escape=\

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

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

COPY ["MyWindowsServiceName/bin/Release/", "/Service/"]

WORKDIR "C:/Service/"

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

ENTRYPOINT ["powershell"]
CMD Start-Service \""MyWindowsServiceName\""; \
    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; \
    }

NOTE1: My windows service logs to the Windows Event system. So this file contains some nice code at the end to print EventLog information to the console, as per Docker convention. You may or may not need this part for your own service. If not, only use the first line minus the '\'.

NOTE2: The name of a windows service may be different to its executable name. That is, 'MyWindowsServiceName.exe' could have a service name of 'My Windows Service Name' or 'Fred', you need to know both.

Upvotes: 14

Parthiva
Parthiva

Reputation: 300

In general, you should choose a base image which has the necessary libraries already installed on it as much as possible instead of taking a very base image such as plain Linux or Windows and installing on it.

In your case, select a docker image which has .NET installed on it.This image for instance The ideal flow is as follows.

  1. Select the Docker Image you want to use
  2. Include a Dockerfile in the root location of your project
  3. Include commands in Dockerfile to copy the code or the executable on to the image
  4. Specify a start command
  5. Build the Image docker build -t YourRepoName . Run this at the location of your Dockerfile
  6. Test it docker run YourImage

Dockerfile This is one of the dockerfiles I wrote for Springboot. You may use it for reference. Please note, I am copy only the jar file here onto my Container and not the source code since at the point of building the docker container, the jar file is available. You may choose to include commands for copying the source code and creating the executable inside the Dockerfile.

Upvotes: -1

Related Questions