Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to connect to net core gRPC service hosted in Docker

I am relatively new to gRPC service.

I am trying to deploy a Net core gRPC service into Linux docker container and accessing it from locally from VS console app.

I want to keep things as simple as possible thus the docker file is identical to a Net core gRPC docker file in VS where docker compose is pointing to it. When running the gRPC service in VS directly, the console app can access the service, just not in docker container.

gRPC launch settings

{
  "profiles": {
    "TrafficGrpc": {
      "commandName": "Project",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "https://localhost:5001"
    },
    "Docker": {
      "commandName": "Docker",
      "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
      "publishAllPorts": true,
      "useSSL": true
    }
  }
}

gRPC app settings

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http2"
    }
  }
}

Docker file

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["gRPC/TrafficGrpc/TrafficGrpc.csproj", "TrafficGrpc/"]
RUN dotnet restore "TrafficGrpc/TrafficGrpc.csproj"
COPY . .
WORKDIR "/src/gRPC/TrafficGrpc"
RUN dotnet build "TrafficGrpc.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "TrafficGrpc.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "TrafficGrpc.dll"]

Docker compose file

version: "3.7"
services:

  # Traffic service
  traffic:
    container_name: traffic
    build:
      context: .
      dockerfile: Dockerfile-traffic
    networks:
      grpc_network:
    environment:
      - SERVICE_NAME=1
    expose:
      - "80"
      - "443"
    ports:
      - "0.0.0.0:32773:80"
      - "0.0.0.0:32774:443"
      
networks:
  grpc_network:

Console app, VS

string trafficUrl = "http://localhost:32773";
//string trafficUrl = "https://localhost:32774";

Traffic traffic = new Traffic
{
    Date = DateTime.Now.AddDays(1),
    Area = Areas[rng.Next(Areas.Length)],
    Condition = Conditions[rng.Next(Conditions.Length)]
};

GrpcChannel tChannel = GrpcChannel.ForAddress(trafficUrl);
TrafficCheckerClient tClient = new TrafficCheckerClient(tChannel);
TrafficConditionResponse tReply = await tClient.CheckTrafficConditionAsync(
    new TrafficConditionRequest { Condition = traffic.Condition }); // <-- ERROR here

After running docker-compose file, the console app is just not able to connect to gRPC.

Using http, I get this error:

Grpc.Core.RpcException
  HResult=0x80131500
  Message=Status(StatusCode=Internal, Detail="Error starting gRPC call. HttpRequestException: An error occurred while sending the request. IOException: The response ended prematurely.")
  Source=System.Private.CoreLib
  StackTrace:
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at ConsoleTestgRPC.Program.<Main>d__5.MoveNext() in D:\Workspace-GW-EV\CL\ConsoleTestgRPC\Program.cs:line 61

Using https, I get this error:

Grpc.Core.RpcException
  HResult=0x80131500
  Message=Status(StatusCode=Internal, Detail="Error starting gRPC call. HttpRequestException: The SSL connection could not be established, see inner exception. IOException: Authentication failed because the remote party has closed the transport stream.")
  Source=System.Private.CoreLib
  StackTrace:
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at ConsoleTestgRPC.Program.<Main>d__5.MoveNext() in D:\Workspace-GW-EV\CL\ConsoleTestgRPC\Program.cs:line 61

At this point, I do not know whether it is a docker network or a gRPC config issue.

I need help to point me in the right direction.

THANK YOU

like image 737
Ed L 005 Avatar asked Nov 07 '22 06:11

Ed L 005


1 Answers

I meet familiar problem today.

You set EXPOSE 80 in the dockerfile, so you need to make grpc to listen the port which bind to it.

So in my case, the grpc listen to the 8099, and expose it to host port: 32812, then client creat channel to it. And it work.

In dockerfile:

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 8099
EXPOSE 443

In server to listen port:

public static IWebHostBuilder CreateHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .ConfigureKestrel(options =>
                {
                    options.ListenAnyIP(
                        8099,
                        listenOptions => { listenOptions.Protocols = HttpProtocols.Http2; }
                    );
                })
                .UseStartup<Startup>();

In client to create channel:

GrpcClientFactory.AllowUnencryptedHttp2 = true;

using var http = GrpcChannel.ForAddress("http://localhost:32812");

Binding port

May this will help you, good luck~

like image 71
Mine Freeman Avatar answered Nov 15 '22 05:11

Mine Freeman