dotnet / Docker.DotNet

:whale: .NET (C#) Client Library for Docker API
https://www.nuget.org/packages/Docker.DotNet/
MIT License
2.23k stars 381 forks source link

Container does not receive stdin input #664

Open bhaeussermann opened 9 months ago

bhaeussermann commented 9 months ago

When I start a container and attach to its input stream, the container does not receive the bytes written to the stream.

Output of dotnet --info:

.NET SDK:
 Version:           8.0.100
 Commit:            57efcf1350
 Workload version:  8.0.100-manifests.8d38d0cc

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19045
 OS Platform: Windows
 RID:         win-x64
 Base Path:   C:\Program Files\dotnet\sdk\8.0.100\

What version of Docker.DotNet?:

3.125.15

Steps to reproduce the issue:

  1. This is my test program (Program.cs) for the container:

    using var input = Console.OpenStandardInput();
    byte[] buffer = new byte[100];
    int bytesCount = input.Read(buffer, 0, buffer.Length);
    Console.WriteLine($"Received {bytesCount} bytes.");

    (The test program is attached to this issue.)

  2. Here is the Dockerfile I'm using to build the Linux image:

    
    FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
    COPY Read.csproj src/Read.csproj
    COPY Program.cs src/Program.cs
    RUN dotnet publish --output out src

FROM mcr.microsoft.com/dotnet/runtime:6.0 AS final WORKDIR /app COPY --from=build out . ENTRYPOINT ["dotnet", "Read.dll"]


3. Build the image using the following command:

docker build -t read .


4. I run the following code to start a container and write to its stdin stream:

using Docker.DotNet; using Docker.DotNet.Models; using System.Text;

using var client = new DockerClientConfiguration().CreateClient(); var response = await client.Containers.CreateContainerAsync(new CreateContainerParameters { Image = "read:latest", AttachStdin = true, // When I set this flag the container never finishes running and the call to WaitContainerAsync() times out. // OpenStdin = true, StdinOnce = true });

await client.Containers.StartContainerAsync(response.ID, new ContainerStartParameters());

using (var inputStream = await client.Containers.AttachContainerAsync(response.ID, tty: false, new() { Stream = true, Stdin = true })) { byte[] bytes = Encoding.UTF8.GetBytes($"Hello{Environment.NewLine}Bye{Environment.NewLine}"); await inputStream.WriteAsync(bytes, 0, bytes.Length, CancellationToken.None); inputStream.CloseWrite(); }

var cancellationTokenSource = new CancellationTokenSource(); cancellationTokenSource.CancelAfter(TimeSpan.FromSeconds(10)); await client.Containers.WaitContainerAsync(response.ID, cancellationTokenSource.Token);

var logs = await client.Containers.GetContainerLogsAsync(response.ID, tty: false, new() { ShowStdout = true, ShowStderr = true }); var (stdOut, stdError) = await logs.ReadOutputToEndAsync(CancellationToken.None); Console.WriteLine($"Output: [{string.Concat(stdOut, stdError)}]");



**What actually happened?:**
The container outputs `Received 0 bytes.` indicating that it's not receiving the input.

As mentioned in the code comment above, if I set `OpenStdin = true` on the `CreateContainerParameters` when creating the container, the container freezes. In particular, by adding some file logging, I can determine that it freezes at the `int bytesCount = input.Read(buffer, 0, buffer.Length);` line.

**What did you expect to happen?:**

The container must output `Received 12 bytes.`

**Additional information:**
[Read.zip](https://github.com/dotnet/Docker.DotNet/files/13658317/Read.zip)