在Docker中运行应用程序时,“无法加载DLL”SQLite.Interop.dll“或其依赖项之一”,但在本地运行正常

qlckcl4x  于 2022-12-03  发布在  Docker
关注(0)|答案(2)|浏览(301)

简介

SQLite.Interop.dll库似乎经常出现问题。看看这些其他的StackOverflow问题:

我已经经历了以上所有和更多:

  • 我安装了System.Data.SQLite.Core NuGet包,
  • 我在*.csproj中指定了these元素,
  • 我设置了x64而不是Any CPU
  • 等等

没有成功。关键因素是应用程序在本地运行良好,但我需要让它在Docker上运行,这就是问题的根源。情况是我正在使用Visual Studio 2022开发**.NET Core 3.1控制台应用程序。应用程序最终将部署在AKS上(Azure Kubernetes Service)。当然,首先我需要在我的开发机器上本地安装Docker。在Visual Studio上构建控制台应用程序项目不会出现错误,并且它可以在Visual Studio中正常运行。使用适当的Docker文件构建其Docker映像也不会出现问题,但在Docker上运行**同一映像会引发以下异常:Unable to load DLL 'SQLite.Interop.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)。当前,该项目安装了System.Data.SQLite.Core NuGet包,并且在*.csproj中没有these元素。该异常由控制台应用程序之一引用的项目引发;此项目同时安装了System.Data.SQLite.CoreSystem.Data.SQLite NuGet包。控制台应用程序的项目只安装了System.Data.SQLite.Core包(我已经尝试安装System.Data.SQLite,但没有成功)。现在,所有项目都安装了System.Data.SQLite NuGet包(尝试给予),这会导致System.Data.SQLite.Core作为依赖项安装.

我所尝试的#

我使用了Visual Studio 2022预组装的Dockerfile,它处理所有各种引用的项目:

FROM mcr.microsoft.com/dotnet/aspnet:3.1 AS base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build
WORKDIR /src
COPY ["ProjectA/ProjectA.csproj", "ProjectA/"]
COPY ["ProjectB/ProjectB.csproj", "ProjectB/"]
#COPY all the other referenced projects
RUN dotnet restore "ProjectA/ProjectA.csproj"
COPY . .
WORKDIR "/src/ProjectA"
RUN dotnet build "ProjectA.csproj" -c Release -o /app/build

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

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

由于此Dockerfile基于多阶段构建,因此它具有以下行:

...
RUN dotnet build "MyProject.csproj" -c Release -o /app/build
...
RUN dotnet publish "MyProject.csproj" -c Release -o /app/publish
...

首先构建代码,然后发布它。考虑到dotnet publish,我决定后退一步,确保至少我能够自己发布项目,以缩小问题范围。我发现在本地文件夹上发布它也给我带来了一些问题,特别是NU 1605错误。这阻止了我成功结束进程。我使用Microsoft建议的方法解决了这个问题。现在,如果我运行位于发布目标文件夹中的.exe,应用程序将按预期工作
是时候把它做成Docker镜像了,镜像构建过程很顺利,但是在运行时出现了Unable...错误,在线阅读,为了解决SQLite.Interop.dll问题,他们建议SQLite.Interop.dll文件直接移到bin文件夹;实际上,最初,我发现它位于bin\Release\netcoreapp3.1\runtimes\文件夹中,在它的win-x86win-x64子目录中。为了“摆脱”这个runtimes文件夹,我尝试将项目发布到本地的一个文件夹中,并使用以下设置:

这实际上使SQLite.Interop.dll直接出现在bin文件夹中,并去掉了runtimes文件夹。因此,为了获得与Docker相同的结果,我修改了Docker文件,如下所示:

...
RUN dotnet build "MyProject.csproj" -c Release -o /app/build -r win-x64
...
RUN dotnet publish "MyProject.csproj" -c Release -o /app/publish -r win-x64
...

现在SQLite.Interop.dll文件也直接出现在Docker运行容器中的bin文件夹中,所以我当时认为一切都很好,但我还是遇到了异常。
最后一件事
我发现,在本地(而不是在Docker中)运行应用程序而不指定目标运行时(因此,将构建过程保持为Any CPU而不是x64),会引发无异常(即,将runtimes/文件夹和其中的两个SQLite.Interop.dll文件保持在win-x86win-x64子文件夹中)。

ar7v8xwq

ar7v8xwq1#

最后我改用了Linux容器。

uinbv5nw

uinbv5nw2#

溶液

要在带有System.Data.SQLite.Core nuget包的windows docker容器中运行dotnet应用程序(例如dotnet test),可以使用以下docker文件

# escape=`
FROM mcr.microsoft.com/windows/servercore:ltsc2019

RUN setx /M PATH "%PATH%;C:\Program Files\dotnet;C:\nodejs"

# Install Microsoft Visual C++ Runtime Library
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';$ProgressPreference='silentlyContinue';"]

# Install .NET 6.0 for x86 (just change it to the platform you need)
RUN Invoke-WebRequest `
            -UseBasicParsing `
            -Uri https://dot.net/v1/dotnet-install.ps1 `
            -OutFile dotnet-install.ps1; `
        ./dotnet-install.ps1 `
            -InstallDir '/Program Files/dotnet' `
            -Channel 6.0 `
            -Architecture x86

下面是我的csproj文件的相关部分:

<ItemGroup>
      ...
      <PackageReference Include="System.Data.SQLite.Core" Version="1.0.117" />
    </ItemGroup>

对我有效的方法
在切换到方法后,安装.NET框架(并且不使用二进制文件)对我来说很有效。
以前,像你一样,我试过很多不同的东西!

您可以尝试

在csproi文件中添加PrivateAssets="none"也是可行的。看到这个答案。在将这个添加到csproj文件中后,我得到了一个不同的错误,因为我必须在我的项目中使用x86-dll。
在正确安装.NET 6 x86之后,我甚至在csproj中恢复了这个更改,它仍然工作!
还有什么
我还尝试了Microsoft Visual C运行时库,但最终没有必要。
引用自https://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki
本网页上所有可下载的软件包,如果其文件名中不包含“static”一词,则在使用其中包含的可执行文件之前,需要在目标计算机上成功安装相应版本(例如2005、2008、2010、2012、2013、2015、2017)的Microsoft Visual C
运行时库。

...
# Install Microsoft Visual C++ Runtime Library
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';$ProgressPreference='silentlyContinue';"]
RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; `
    Invoke-WebRequest "https://aka.ms/vs/17/release/vc_redist.x64.exe" -OutFile "vc_redist.x64.exe"; `
    Start-Process -filepath C:\vc_redist.x64.exe -ArgumentList "/install", "/passive", "/norestart" -Passthru | Wait-Process; '
    Remove-Item -Force vc_redist.x64.exe;

有关在Docker容器中 How-To 安装.NET的详细信息,请参阅at the dotnet-docker github repo

TL/DR

在你的dockerfile中使用dotnet-install.ps1来安装.NET和SDK。不知何故,它有一些魔力,所以你可以运行使用SQLite.Interop.dll库的dotnet应用程序(通过nuget包含)

相关问题