无法在基于alpine的dotnet SDK中运行gRPC protoc

问题描述 投票:1回答:1

看到这个github问题:https://github.com/grpc/grpc/issues/18338

请参阅此示例repo:https://github.com/slolife/alpine-protoc

如果我在项目中包含Grpc.Tools 1.19.0 nuget包,它会添加一个构建步骤<Protobuf Include="Test.proto" />

如果我创建一个docker镜像来构建并使用microsoft/dotnet:2.2-sdk作为构建图像,这可以正常工作。但是,如果我尝试使用基于alpine的microsoft/dotnet:2.2-sdk-alpine构建映像,则构建将失败,并显示以下错误消息:

/root/.nuget/packages/grpc.tools/1.19.0/build/_protobuf/Google.Protobuf.Tools.targets(263,5): error MSB6003: The specified task executable "/root/.nuget/packages/grpc.tools/1.19.0/tools/linux_x64/protoc" could not be run. No such file or directory [/src/alpine-protoc.csproj]

我确认protoc文件位于错误消息抱怨的位置。

我尝试运行apk add libc6-compat并重新运行构建。这次我收到以下错误:

/root/.nuget/packages/grpc.tools/1.19.0/build/_protobuf/Google.Protobuf.Tools.targets(263,5): error MSB6006 : "/root/.nuget/packages/grpc.tools/1.19.0/tools/linux_x64/protoc" exited with code 139. [/src/alpine-proto c.csproj]


更新:ldd protoc的输出

~/.nuget/packages/grpc.tools/1.19.0/tools/linux_x64 # ldd protoc
/lib64/ld-linux-x86-64.so.2 (0x7f60935a7000)
libm.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7f60935a7000)
libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7f60935a7000)
libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7f60935a7000)
.net-core grpc alpine
1个回答
1
投票

这似乎是一个libc兼容性问题 - 我最好的猜测是dotnet拉大陆,glibc兼容protoc和grpc。

阿尔卑斯山的No such file or directory错误。当运行存在且可访问的可执行文件时,ld无法解析依赖库(例如libc.so.6)。

ldd protoc输出我们可以看到protoc需要libc.so.6,所以它很可能是在带有glibc的Linux上构建的,比如Ubuntu或Debian。 libc6-compat包在musl libc之上提供了一个兼容层,以允许基本的glibc功能,例如,添加所需的库文件和缺少的函数。但是,它不能提供完全的glibc兼容性。取决于glibc的复杂应用程序在与musl libc链接时不太可能开箱即用,至少在没有一些移植工作的情况下。

当你添加libc6-compat时,protoc能够链接到musl-glibc兼容性库libc.so.6等,但是当用代码139退出时,意味着它被分割(得到一个SIGSEGV)。这是一个很好的迹象,你必须使用它与实际的glibc。一个可能的原因是默认堆栈大小:musl libc创建的线程具有非常小的默认堆栈大小,大约68kb,而glibc线程创建为2-8MB堆栈。有关其他细微差别,请参阅:https://wiki.musl-libc.org/functional-differences-from-glibc.html

您可以尝试使用简单的hack来解决nuget包inccompatility:使用Alpine compatible protobuf安装apk add protobuf编译器;然后,用一个符号链接替换你的protoc/usr/bin/protoc

或者,您可以尝试在Alpine上安装适当的glibc,方法是将以下内容添加到Dockerfile中(感谢sgerrandanapsix):

ENV GLIBC_REPO=https://github.com/sgerrand/alpine-pkg-glibc
ENV GLIBC_VERSION=2.28-r0

RUN set -ex && \
    apk --update add libstdc++ curl ca-certificates && \
    for pkg in glibc-${GLIBC_VERSION} glibc-bin-${GLIBC_VERSION}; \
        do curl -sSL ${GLIBC_REPO}/releases/download/${GLIBC_VERSION}/${pkg}.apk -o /tmp/${pkg}.apk; done && \
    apk add --allow-untrusted /tmp/*.apk && \
    rm -v /tmp/*.apk && \
    /usr/glibc-compat/sbin/ldconfig /lib /usr/glibc-compat/lib
© www.soinside.com 2019 - 2024. All rights reserved.