请参见以下github问题:https://github.com/grpc/grpc/issues/18338
请参阅以下示例存储库:https://github.com/slolife/alpine-protoc
如果我在项目中包含 Grpc.Tools 1.19.0 nuget程序包,它会添加一个构建步骤<Protobuf Include="Test.proto" />
如果我创建要构建的docker映像并将microsoft/dotnet:2.2-sdk
用作生成映像,则此方法很好。但是,如果我尝试使用基于高山的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)
答案 0 :(得分:1)
这似乎是一个libc兼容性问题-我的最佳猜测是dotnet将glibc兼容protoc
与grpc一起推向了大陆。
Alpine上的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兼容性。当与musl libc链接时,依赖于glibc的复杂应用程序不可能即开即用,至少在没有一些移植工作的情况下也是如此。
当您添加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。
您可以尝试使用简单的技巧来解决nuget软件包不兼容的问题:使用apk add protobuf
安装Alpine compatible protobuf编译器;然后,将您的protoc
替换为指向/usr/bin/protoc
的符号链接。
或者,您可以尝试通过在Dockerfile中添加以下内容(由于sgerrand和anapsix)在Alpine上安装适当的glibc:
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