4

I want to have 2 windows containers - running on same host (using windows 10 client machine and docker for windows) talking via a named pipe (not anonymous pipes). However, I couldn't make it work.

My named pipe server class is here in GitHub. The code is from Microsoft Docs, in a nutshell:

    private  void ServerThread(object data)
    {
        NamedPipeServerStream pipeServer =
            new NamedPipeServerStream(this.pipeName, PipeDirection.InOut, numThreads);
        int threadId = Thread.CurrentThread.ManagedThreadId;
        pipeServer.WaitForConnection();
        try
        {
            StreamString ss = new StreamString(pipeServer);
            ss.WriteString("I am the one true server!");
            string message = ss.ReadString();

            ss.WriteString($"Server message {DateTime.Now.ToLongTimeString()}");
        }
        catch (IOException e)
        {
            Console.WriteLine("ERROR: {0}", e.Message);
        }
        pipeServer.Close();
    }

And the client side code (also from Microsoft Docs) is in the same GitHub repo. Essentially the code is following:

    private static void RunCore(string ip, string pipeName)
    {
        NamedPipeClientStream pipeClient =
                new NamedPipeClientStream(ip, pipeName,
                    PipeDirection.InOut, PipeOptions.None,
                    TokenImpersonationLevel.Impersonation);
        pipeClient.Connect();

        StreamString ss = new StreamString(pipeClient);
        if (ss.ReadString() == "I am the one true server!")
        {
            ss.WriteString("Message from client " + DateTime.Now.ToString());
            Console.Write(ss.ReadString());
        }
        else
        {
            Console.WriteLine("Server could not be verified.");
        }
        pipeClient.Close();
    }

The entire project is in this GitHub directory.

If I now run this on my local machine, the client can reach to server (I see console messages both in client and server). Then I put the executable in a container using the following docker file:

FROM mcr.microsoft.com/dotnet/framework/runtime:4.8
WORKDIR /app
COPY ./bin/release/ ./
ENTRYPOINT ["C:\\app\\Namedpipe.exe"]

Now, on windows 10 client machine (with Docker for Windows) I launch the server as:

docker run -it -v \\.\pipe\helloworld:\\.\pipe\helloworld named-pipe-net-framework:latest

At this point, I verified that I have a named pipe (name 'helloworld') in my host (using pipelist.exe). Then I lunch the container in client mode as:

docker run -it -v \\.\pipe\helloworld:\\.\pipe\helloworld  named-pipe-net-framework:latest

But the client can never reach to the pipe (it takes a long time freezed and then fails). However, I have lunched a powershell inside the client container (using docker exec) and can run pipelist.exe and see the named pipe 'helloworld' is available. But the code doesn't work. Can anybody give me some pointers why this doesn't work?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Moim
  • 486
  • 1
  • 8
  • 23

1 Answers1

2

What I found is that only client pipes can connect from within container to a server pipe opened on the host.

Also it worked (for me) only when I used C++ WIN32 API to create such pipe, I had the same freeze when using NamedPipeClientStream of .NET. Creating a server pipe in the container, regardless of the technology, resulted in error, presumably because it was already occupied by the mapping in the container.

This effectively means that one can't directly connect 2 containers via a named pipe, as both would be client pipes and they can only connect to a server pipe on the host.

I believe that the mapping of named pipes in Windows is achieved by using a couple of extra pipes on the container (server pipe) and on the host (client pipe), and the messages a travelling via a chain of 4 connected pipes: serverhost-clienthost-servercontainer-clientcontainer.

Took me few days of searching the internet for this same info, with no luck. Almost every case about named pipe behavior in Windows containers is about accessing Docker API from within container. One can even start doubting if it could support something else.

  • Hi @Gediminas, Do you have some idea on https://stackoverflow.com/questions/61363499/memorymappedfiles-in-c-sharp-for-ipc-between-docker-containers question. I felt we are looking in for something similar down the line. – H S Raju Apr 24 '20 at 11:34