5

I have made a simple Grpc Greeter Service along with a client. When the service is hosted on localhost, client is able to call the rpc and receive the response. But when the Service is running inside docker container on localhost, the client is not able to connect to the service.

** Grpc Service Server **

namespace GreeterServer
{
    class Program
    {
        private readonly static ManualResetEvent shutdown = new ManualResetEvent(false);
        static void Main(string[] args)
        {
            int port = 5000;
            Console.WriteLine("Hello World!");
            Server server = new Server{
                Services = {GreeterService.BindService(new GreeterController())},
                Ports = {new ServerPort("localhost", port, ServerCredentials.Insecure)}
            };
            server.Start();
            Console.WriteLine("Grpc Server started");
            Console.Read();
            shutdown.WaitOne();
        }
    }
}

** Dockerfile for the Grpc Service **

FROM microsoft/dotnet:2.1-sdk as base
WORKDIR /app

COPY *.csproj .
RUN dotnet restore

COPY . .
RUN dotnet build -c Release -o out

FROM microsoft/dotnet:2.1-runtime
WORKDIR /app
COPY --from=base /app/out .
ENTRYPOINT ["dotnet", "GreeterServer.dll"]
EXPOSE 5000

** Grpc Client **

namespace GreeterClient
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Hello World!");
                Channel channel = new Channel("127.0.0.1:5000", ChannelCredentials.Insecure);
                GreeterService.GreeterServiceClient client = new GreeterService.GreeterServiceClient(channel);
                HelloRequest request = new HelloRequest
                {
                    Message = "Hi From Client"
                };
                HelloResponse response = client.SayHello(request);
                Console.WriteLine(response.Message);
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
            }

        }
    }
}

** Stacktrace from the Grpc Client **

Grpc.Core.RpcException: Status(StatusCode=Unknown, Detail="Stream removed")
   at Grpc.Core.Internal.AsyncCall`2.UnaryCall(TRequest msg) in T:\src\github\grpc\src\csharp\Grpc.Core\Internal\AsyncCall.cs:line 75
   at Grpc.Core.DefaultCallInvoker.BlockingUnaryCall[TRequest,TResponse](Method`2 method, String host, CallOptions options, TRequest request) in T:\src\github\grpc\src\csharp\Grpc.Core\DefaultCallInvoker.cs:line 46
   at Grpc.Core.Interceptors.InterceptingCallInvoker.<BlockingUnaryCall>b__3_0[TRequest,TResponse](TRequest req, ClientInterceptorContext`2 ctx) in T:\src\github\grpc\src\csharp\Grpc.Core\Interceptors\InterceptingCallInvoker.cs:line 51
   at Grpc.Core.ClientBase.ClientBaseConfiguration.ClientBaseConfigurationInterceptor.BlockingUnaryCall[TRequest,TResponse](TRequest request, ClientInterceptorContext`2 context, BlockingUnaryCallContinuation`2 continuation) in T:\src\github\grpc\src\csharp\Grpc.Core\ClientBase.cs:line 174
   at Grpc.Core.Interceptors.InterceptingCallInvoker.BlockingUnaryCall[TRequest,TResponse](Method`2 method, String host, CallOptions options, TRequest request) in T:\src\github\grpc\src\csharp\Grpc.Core\Interceptors\InterceptingCallInvoker.cs:line 48
   at Greeter.Proto.GreeterService.GreeterServiceClient.SayHello(HelloRequest request, CallOptions options) in F:\c#\GrpcPracticeWithDocker\GreeterClient\GrpcClasses\GreeterGrpc.cs:line 70
   at Greeter.Proto.GreeterService.GreeterServiceClient.SayHello(HelloRequest request, Metadata headers, Nullable`1 deadline, CancellationToken cancellationToken) in F:\c#\GrpcPracticeWithDocker\GreeterClient\GrpcClasses\GreeterGrpc.cs:line 66
   at GreeterClient.Program.Main(String[] args) in F:\c#\GrpcPracticeWithDocker\GreeterClient\Program.cs:line 23
kumarmo2
  • 1,381
  • 1
  • 20
  • 35

2 Answers2

6

(1) Do not use localhost in your GRPC server inside docker, it will not work as the loopback localhost cannot be reached from outside docker, you need to listen on all interfaces, so use "0.0.0.0", eg.

Ports = {new ServerPort("0.0.0.0", port, ServerCredentials.Insecure)}

Here is a stack that refers to this issue: Cannot connect to Go GRPC server running in local Docker container

(2) I had this same issue. I found that the issue was the I was not using an interactive shell when using docker run or docker compose. If you are using docker run then you need to use the -it commands, and for docker compose you need to use stdin_open: true and tty:true.

Docker run example

docker run --name grpcserver -p 8081:8081 -it -d grpcserver

Docker compose example

version: '3'

services:
  web:
    container_name: mynginx
    build:
      context: ./nginx
      dockerfile: Dockerfile
    ports:
      - 8080:80
  grpcserver:
    image: grpcserver
    container_name: grpcserver
    stdin_open: true
    tty: true
    build:
      context: .
      dockerfile: Dockerfile

Here is another stack that talks about this: Interactive shell using Docker Compose

Good luck!

spirasean
  • 61
  • 2
1

I came across the same issue. But finally it is related with proxy configuration. GRPC uses "HTTP_PROXY" and "HTTPS_PROXY" environment configuration. Unfortunately my grpc server running on local network which does not require a proxy. I missed to define the "NO_PROXY" environment variable.

Once I added the grpc server ip into the NO_PROXY, it started working.

Note:

  1. I am able to get docker working with just "localhost". I have not bounded my grpc server to "0.0.0.0"
  2. I diagnosed the problem by enabling the GRPC tracing logging. After enabled the tracing you have to use the following code to show the logs into the console.

ref: https://github.com/grpc/grpc/blob/master/TROUBLESHOOTING.md

GrpcEnvironment.SetLogger(new ConsoleLogger());
Prakash P
  • 100
  • 1
  • 7
  • 1
    The syntax for adding the NO_PROXY environemnt variable is: Environment.SetEnvironmentVariable("NO_PROXY", "localhost") – jumpercake Jul 01 '19 at 21:24