Reputation: 79
I have two .net core microservices(PatientService and AppointmentService) with normal web APIs and gRPC service. I am using gRPC for inter service communication instead of using HTTP calls.
Appointment service depends upon patient service for data, meaning when I hit a endpoint on appointment service to get appointments I need patient information from patient service, so I am using gRPC for this call.
Now my application is working just fine and I am able to communicate between two, without doing any extra stuff using kestrel on my local environment. But when I run the same application in Docker the application does not run, I am not able to hit neither HTTP1 nor HTTp2 ports. I am running Linux containers.
My question is how to run HTTP1 and HTTP2 in a .net core application? How to do inter service communication in .net microservices using grpc?
How to run .net core web API + gRPC service in docker using Linux containers(Ubuntu 18.04)? How to run gRPC without TLS?
Please help I have tried everything and I am stuck.I have this important build to release.
Docker File.
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
RUN sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/g' /etc/ssl/openssl.cnf
RUN sed -i 's/MinProtocol = TLSv1.2/MinProtocol = TLSv1/g' /etc/ssl/openssl.cnf
RUN sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/g' /usr/lib/ssl/openssl.cnf
RUN sed -i 's/MinProtocol = TLSv1.2/MinProtocol = TLSv1/g' /usr/lib/ssl/openssl.cnf
WORKDIR /app
EXPOSE 80
EXPOSE 6002
EXPOSE 443
EXPOSE 5001
EXPOSE 6001
#our sql server was use this port for connect
EXPOSE 7007
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["API/API.csproj", "API/"]
COPY ["Infrastructure/Infrastructure.csproj", "Infrastructure/"]
COPY ["Application/Application.csproj", "Application/"]
COPY ["Domain/Domain.csproj", "Domain/"]
COPY ["Common/Common.csproj", "Common/"]
RUN dotnet restore "API/API.csproj"
COPY . .
WORKDIR "/src/API"
RUN dotnet build "API.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "API.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "API.dll"]
Upvotes: 7
Views: 5503
Reputation: 441
I found a solution which works for me, it took me just 3 weeks to figure it out.
There are 3 main concerns:
Kestrel should be set with following parameters in appsetting.json or in the program cs which one you prefer:
"Kestrel": {
"EndPoints": {
"Grpc": {
"Url": "http://*:8080",
"Protocols": "Http2"
},
"webApi": {
"Protocols": "Http1",
"Url": "http://*:80"
}
}
}
OR
ConfigureKestrel(options =>
{
options.ListenAnyIP(80, listenOptions => listenOptions.Protocols = HttpProtocols.Http1); //webapi
options.ListenAnyIP(8080, listenOptions => listenOptions.Protocols = HttpProtocols.Http2); //grpc
})
After this setting, you start the docker with following commands (ports and ip may differ as you wish, make sure there is no other thing listening on those ports ips):
docker run -p 127.0.0.40:8080:80 -p 127.0.0.40:8081:8080 --env ASPNETCORE_ENVIRONMENT=Development -it my_project -e ASPNETCORE_ENVIRONMENT=Development -e ASPNETCORE_URLS=http://+
After this u have to configure your channel (do not use the ".AddGrpcClient" extension from Grpc.AspNetCore):
services.AddSingleton(x =>
{
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
return GrpcChannel.ForAddress("127.0.0.40:8081",
//TODO:GRPC Root SSL Creds
channelOptions: new GrpcChannelOptions()
{
Credentials = ChannelCredentials.Insecure
});
});
After this you create your clients as you wish with the Channel you created and it should be fine whatever you want to do. No other method worked for me.
UPDATE: I found a way to make it work with "AddGrpcClient" from Grpc.AspNetCore.
services.AddGrpcClient<ControllerGuide.GuideClient>(
(x, opt) =>
{
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
opt.Address = new Uri("UriGRPC:5001");
opt.ChannelOptionsActions.Add(act =>
{
act.Credentials = ChannelCredentials.Insecure;
});
});
Upvotes: 10