This sample GIST contains sample code that describes how to modify an NT service that implements a simple HTTP server for Windows to migrate the application to a container.
Last active
March 25, 2024 08:25
-
-
Save rkttu/865889fa4b1065ff4ca53af10dbd310d to your computer and use it in GitHub Desktop.
Windows NT Service Containerisation Examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@echo off | |
pushd "%~dp0" | |
%windir%\Microsoft.NET\Framework64\v4.0.30319\csc.exe /nologo /target:exe /r:System.ServiceProcess.dll /out:ServiceMain.exe ServiceMain.cs | |
%windir%\Microsoft.NET\Framework64\v4.0.30319\csc.exe /nologo /target:exe /out:SimpleMain.exe SimpleMain.cs | |
:exit | |
popd | |
@echo on |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@echo off | |
pushd "%~dp0" | |
if exist *.exe del /f /q *.exe | |
:exit | |
popd | |
@echo on |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@echo off | |
pushd "%~dp0" | |
docker.exe build -t simpleweb:latest -f Dockerfile_Simple . | |
:exit | |
popd | |
@echo on |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FROM mcr.microsoft.com/windows/servercore:ltsc2022 AS BUILD | |
WORKDIR /build | |
ADD . . | |
RUN C:/Windows/Microsoft.NET/Framework64/v4.0.30319/csc.exe /nologo /target:exe /out:SimpleMain.exe SimpleMain.cs | |
FROM mcr.microsoft.com/windows/servercore:ltsc2022 | |
USER ContainerAdministrator | |
WORKDIR /server | |
COPY --from=BUILD /build/SimpleMain.exe . | |
EXPOSE 8000 | |
USER ContainerUser | |
CMD ["SimpleMain.exe"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@echo off | |
pushd "%~dp0" | |
docker.exe rm -f simpleweb > NUL | |
docker.exe run -dt -p 80:8000 --name simpleweb simpleweb:latest | |
:exit | |
popd | |
@echo on |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Net; | |
using System.Net.Sockets; | |
using System.Text; | |
using System.Threading; | |
using System.ServiceProcess; | |
class HttpServerService : ServiceBase | |
{ | |
private Thread serverThread; | |
public HttpServerService() | |
{ | |
this.ServiceName = "HttpServerService"; | |
} | |
protected override void OnStart(string[] args) | |
{ | |
serverThread = new Thread(ServerThread); | |
serverThread.Start(); | |
} | |
protected override void OnStop() | |
{ | |
serverThread.Abort(); | |
} | |
static void ServerThread() | |
{ | |
TcpListener server = new TcpListener(IPAddress.Any, 8000); | |
server.Start(); | |
while (true) | |
{ | |
TcpClient client = server.AcceptTcpClient(); | |
Thread thread = new Thread(() => HandleClientThread(client)); | |
thread.Start(); | |
} | |
} | |
static void HandleClientThread(TcpClient client) | |
{ | |
NetworkStream stream = client.GetStream(); | |
byte[] request = new byte[1024]; | |
stream.Read(request, 0, request.Length); | |
Console.WriteLine(Encoding.UTF8.GetString(request)); | |
string response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<html><body><h1>Hello, World!</h1></body></html>"; | |
byte[] responseBytes = Encoding.UTF8.GetBytes(response); | |
stream.Write(responseBytes, 0, responseBytes.Length); | |
client.Close(); | |
} | |
} | |
class Program | |
{ | |
static void Main() | |
{ | |
ServiceBase.Run(new HttpServerService()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Net; | |
using System.Net.Sockets; | |
using System.Text; | |
using System.Threading; | |
using System.Runtime.InteropServices; | |
class Program | |
{ | |
private static TcpListener server; | |
private static bool isRunning = true; | |
static void Main() | |
{ | |
SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true); | |
Thread thread = new Thread(ServerThread); | |
thread.Start(); | |
thread.Join(); | |
} | |
private static bool ConsoleCtrlCheck(CtrlTypes ctrlType) | |
{ | |
if (ctrlType == CtrlTypes.CTRL_CLOSE_EVENT || ctrlType == CtrlTypes.CTRL_BREAK_EVENT || ctrlType == CtrlTypes.CTRL_C_EVENT || | |
/* CTRL_SHUTDOWN_EVENT signal is sent when you run the docker stop command. */ | |
ctrlType == CtrlTypes.CTRL_SHUTDOWN_EVENT) | |
{ | |
isRunning = false; | |
server.Stop(); | |
Console.WriteLine("Server is shutting down..."); | |
} | |
return true; | |
} | |
static void ServerThread() | |
{ | |
server = new TcpListener(IPAddress.Any, 8000); | |
server.Start(); | |
while (isRunning) | |
{ | |
if (!server.Pending()) | |
{ | |
Thread.Sleep(500); // choose a delay that makes sense for you | |
continue; | |
} | |
TcpClient client = server.AcceptTcpClient(); | |
Thread thread = new Thread(() => HandleClientThread(client)); | |
thread.Start(); | |
} | |
} | |
static void HandleClientThread(TcpClient client) | |
{ | |
NetworkStream stream = client.GetStream(); | |
byte[] request = new byte[1024]; | |
stream.Read(request, 0, request.Length); | |
Console.WriteLine(Encoding.UTF8.GetString(request)); | |
string response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<html><body><h1>Hello, World!</h1></body></html>"; | |
byte[] responseBytes = Encoding.UTF8.GetBytes(response); | |
stream.Write(responseBytes, 0, responseBytes.Length); | |
client.Close(); | |
} | |
#region unmanaged | |
// Declare the SetConsoleCtrlHandler function | |
// as external and receiving a delegate. | |
[DllImport("Kernel32")] | |
public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add); | |
// A delegate type to be used as the handler routine | |
// for SetConsoleCtrlHandler. | |
public delegate bool HandlerRoutine(CtrlTypes CtrlType); | |
// An enumerated type for the control messages | |
// sent to the handler routine. | |
public enum CtrlTypes | |
{ | |
CTRL_C_EVENT = 0, | |
CTRL_BREAK_EVENT, | |
CTRL_CLOSE_EVENT, | |
CTRL_LOGOFF_EVENT = 5, | |
CTRL_SHUTDOWN_EVENT | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment