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
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~
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With