在 Docker Alpine 映像上运行时,带有 DB2 的 ASP.NET Core 在第一次请求时退出,代码为 139

时间:2021-02-19 22:29:59

标签: docker asp.net-core dockerfile asp.net-core-3.1 alpine

我正在构建一个 ASP.NET Core 3.1 应用程序,它使用 IBM.Data.DB2.Core-lnx 访问旧应用程序的数据库。它在使用普通 Debian 映像时有效。但我想使用 Alpine 来代替较小的图像。我有一些关于丢失文件的错误:

<块引用>

加载共享库 libpam.so.0 时出错:没有那个文件或目录(/app/clidriver/lib/liblibdb2.so 需要)

使用 content search,我找到了包含它们的 Alpine 包。但是该应用程序显示了一个奇怪的行为:它启动并一直运行,直到我在浏览器中打开它的网站。我打开它后,容器退出并显示错误代码 139 并且没有消息:

db2_test_1  | info: Microsoft.Hosting.Lifetime[0]
db2_test_1  |       Now listening on: http://0.0.0.0:5000
db2_test_1  | info: Microsoft.Hosting.Lifetime[0]
db2_test_1  |       Application started. Press Ctrl+C to shut down.
db2_test_1  | info: Microsoft.Hosting.Lifetime[0]
db2_test_1  |       Hosting environment: Development
db2_test_1  | info: Microsoft.Hosting.Lifetime[0]
db2_test_1  |       Content root path: /app
db2test_db2_test_1 exited with code 139

我尝试用一​​个虚拟的 sleep 命令替换我的入口点,并通过使用 docker exec 在容器中打开一个 shell 来手动启动应用程序:

/app # dotnet DB2Test.dll
warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
      Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
      No XML encryptor configured. Key {53574556-0fee-4926-b1f3-6c57cdfd395a} may be persisted to storage in unencrypted form.
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: http://0.0.0.0:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /app
Segmentation fault (core dumped)

我不知道为什么会发生这种情况。我的 Dockerfile:

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine AS sdk-image
WORKDIR /app
COPY DB2Test.csproj .
RUN dotnet restore
COPY . .
RUN dotnet publish -c Debug -o /publish

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine AS runtime-image
WORKDIR /app
COPY --from=sdk-image /publish .
#RUN apk add libxml2-dev openssl-dev zlib zlib-dev libressl libressl-dev libc6-compat linux-pam
RUN apk add libxml2-dev libc6-compat linux-pam

ARG ASPNETCORE_ENVIRONMENT=Development
ENV ASPNETCORE_URLS=http://0.0.0.0:5000
ENV ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT}
ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/app/clidriver/lib"

ENTRYPOINT ["dotnet", "DB2Test.dll"]

以及完整 Debian 构建的 Dockerfile:

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS sdk-image
WORKDIR /app
COPY DB2Test.csproj .
RUN dotnet restore
COPY . .
RUN dotnet publish -c Debug -o /publish

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS runtime-image
WORKDIR /app
COPY --from=sdk-image /publish .
RUN apt-get update \
    && apt-get install -y libxml2-dev

ARG ASPNETCORE_ENVIRONMENT=Development
ENV ASPNETCORE_URLS=http://0.0.0.0:5000
ENV ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT}
# https://gist.github.com/StevenLiekens/dacbd8cdef93d20bf7fcfc2bdafbce43
ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/app/clidriver/lib"

ENTRYPOINT ["dotnet", "DB2Test.dll"]

如您所见,基本相同。我只是为 Alpine 安装了缺失的 apk 包。

ASP.NET Core 应用程序本身没什么特别的:带有两个包的 VS Razor Pages 模板

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Dapper" Version="2.0.78" />
    <PackageReference Include="IBM.Data.DB2.Core" Version="3.1.0.400" Condition="'$(OS)' == 'WINDOWS_NT'"/>
    <PackageReference Include="IBM.Data.DB2.Core-lnx" Version="3.1.0.400" Condition="'$(OS)' == 'UNIX'"/>
  </ItemGroup>

</Project>

IndexModel 打开一个 DB2 连接并从数据库中获取一些数据(它是一个测试数据库,获取了 2 行)

public class IndexModel : PageModel {
    private readonly ILogger<IndexModel> _logger;
    public List<Community> Communities { get; private set; }

    public IndexModel(ILogger<IndexModel> logger) {
        _logger = logger;
    }

    public void OnGet() {
        String MyDb2ConnectionString = "Server=cnx-db2:50000;database=SNCOMM;uid=lcuser;pwd=xx;";
        DB2Connection db = new DB2Connection(MyDb2ConnectionString);
        db.Open();
        Communities = db.Query<Community>(@"SELECT COMMUNITY_UUID as Uid, NAME, LOWER_NAME AS LowerName, DESCRIPTION FROM SNCOMM.COMMUNITY")
            .ToList();
    }
}

我认为崩溃与 IBM 的 DB2 库有关,因为它是在第一个请求期间执行的(这个测试应用程序中还没有 DI 或其他东西,如您在上面看到的,它在执行 GET 请求时首先初始化) .

1 个答案:

答案 0 :(得分:0)

我并不完全熟悉 IBM DB2,但它可能与 Alpine Linux 不兼容,至少在您运行的特定版本中是这样。
由于您能够确认 DB2 本身存在段错误(退出代码 139 表示发生了 SIGSEGV),因此很可能是这种情况。

Alpine Linux 基于 musl libc 库,而不是 glibc,即 GNU C 库。 libc 库提供 C 标准库实现和 POSIX API,因此它支持大多数 Linux 程序,并且是 Linux 系统的基本部分。虽然 musl 旨在保持与 glibc 的兼容性,但在实践中存在许多兼容性问题,这将阻止在基于 glibc 的 Linux 发行版(例如 Ubuntu、Debian、RHEL)上编译的程序在基于 musl libc 的发行版(例如 Alpine 和 Void Linux)上运行),如果它们是动态链接的。例如:musl libc 上的默认线程堆栈大小为 128KB,而 glibc 上为 4MB - 这很可能是复杂软件中段错误的原因。还有许多其他细微差别,涵盖here

通过谷歌搜索,我在 Github issue 项目中发现了以下 node-ibm_db,IBM 项目成员发表了以下评论(日期正好是 1 年前,20/2/20):

<块引用>

node-ibm_db 适用于 amazonlinux、ubuntu 和 debian 的 Linux-x86-64 映像。它不能在 alpine 上工作,因为 IBM Db2 客户端安装程序不是在 alpine linux 上使用 musl libc 编译的。因此,IBM Driver for Db2 都不适用于 alpine linux。

这似乎证实了 IBM DB2 目前不支持 Alpine Linux。