91378246
91378246

Reputation: 377

.NET Core 3.1 gRPC Docker: Could not make proto path relative

Problem description

Publishing a default .NET Core 3.1 gRPC service (generated by Visual Studio Community 2019 16.5.4) via Docker fails due to Could not make proto path relative : error : Protos/GreeterService.proto: No such file or directory [/src/ProjectName/ProjectName.csproj].

How to reproduce

  1. Create a new gRPC Project with .net Core 3.1 and Docker support (Linux)
  2. Open the generated Dockerfile
  3. Remove the directory from the copy path of the first COPY (this is an error in the default Dockerfile):

    COPY ["ProjectName/ProjectName.csproj", "ProjectName/"] => COPY ["ProjectName.csproj", "ProjectName/"]

  4. Run docker build .

Now the line RUN dotnet build "ProjectName.csproj" -c Release -o /app/build throws an error:

Protos : warning : directory does not exist. [/src/ProjectName/ProjectName.csproj]
Could not make proto path relative : error : Protos/GreeterService.proto: No such file or directory [/src/ProjectName/ProjectName.csproj]

But if you go into the container, the file actually exists at exactly this location:

root@1b49365bc690:/src/ProjectName# ls
ProjectName.csproj  obj

What I tried

I couldn't find much regarding this issue, therefore the only helpful seeming answer I found was this SO answer which recommends to add ProtoRoot="Protos" within the .csproj file, but sadly this didn't help.

Furthermore I tried to manually execute the dotnet build command from different working directories with various target path combinations but none worked. The verbose flag also didn't provide any useful information:

    Task "ProtoCompile"
      /root/.nuget/packages/grpc.tools/2.27.0/tools/linux_x64/protoc --csharp_out=obj/Release/netcoreapp3.1 --plugin=protoc-gen-grpc=/root/.nuget/packages/grpc.tools/2.27.0/tools/linux_x64/grpc_csharp_plugin --grpc_out=obj/Release/netcoreapp3.1 --grpc_opt=no_client --proto_path=/root/.nuget/packages/grpc.tools/2.27.0/build/native/include --proto_path=Protos --dependency_out=obj/Release/netcoreapp3.1/1255d1a520d30ea4_greet.protodep --error_format=msvs Protos/greet.proto
1:7>Protos : warning : directory does not exist. [/src/ProjectName/ProjectName.csproj]
1:7>Could not make proto path relative : error : Protos/greet.proto: No such file or directory [/src/ProjectName/ProjectName.csproj]

I hope someone can help me out with this problem; thank you in advance.

Ressources

Dockerfile:

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 ["ProjectName.csproj", "ProjectName/"]
RUN dotnet restore "ProjectName/ProjectName.csproj"
COPY . .
WORKDIR "/src/ProjectName"
RUN dotnet build "ProjectName.csproj" -c Release -o /app/build

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

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

greet.proto:

syntax = "proto3";

option csharp_namespace = "ProjectName";

package greet;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply);
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

.csproj

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <UserSecretsId>secretsId</UserSecretsId>
    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
  </PropertyGroup>

  <ItemGroup>
    <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Grpc.AspNetCore" Version="2.27.0" />
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.8" />
  </ItemGroup>

</Project>

Upvotes: 2

Views: 6400

Answers (2)

GregTheDev
GregTheDev

Reputation: 623

Adding a comment here as I had the same Error message but for a different reason. In my case, I was on Windows building a Linux docker image.

In my csproj, the Proto was included as "Protos\MyService.proto" - turns out on the filesystem the filename was Myservice.proto (lowercase 's') - obviously the Linux build container is case sensitive, hence; "No such file or directory"!

Easy fix but took me about an hour of head scratching 😁

Upvotes: 11

91378246
91378246

Reputation: 377

I got it to work by changing the Dockerfile to following:

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 "ProjectName.csproj" .
RUN dotnet restore "ProjectName.csproj"
COPY . .
RUN dotnet build "ProjectName.csproj" -c Release -o /app/build

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

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

I'm not 100% sure why this works, but I guess that it has something to do with how the gRPC compiler discovers which files it has to compile.

Upvotes: -1

Related Questions