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.
- The container stays up as long as this process is running.
- 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.
- 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/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.