Pine Code
Pine Code

Reputation: 2787

“Unable to load DLL 'SQLite.Interop.dll' or one of its dependencies” in Docker, but locally it works

Introduction

There seem to be issues with the SQLite.Interop.dll library:

I’ve gone through all of the above and:

with no success. The application runs fine locally but I need to make it run on Docker. I’m working on a .NET Core 3.1 console application with Visual Studio 2022. The application will be deployed on Azure Kubernetes Service. First I need to make it work on the local installation of Docker. Building the console application project gives no error and it runs fine from Visual Studio. Building its Docker image with the Dockerfile also gives no problems, but running the same image on Docker raises:

Unable to load DLL 'SQLite.Interop.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)

The project has the System.Data.SQLite.Core NuGet package installed and doesn’t have these elements in the *.csproj. The exception is raised by a project referenced by the console application; this project has System.Data.SQLite.Core and System.Data.SQLite NuGet packages installed. The console application’s project has only the System.Data.SQLite.Core package installed (I tried to install System.Data.SQLite, with no success). All projects now have the System.Data.SQLite NuGet package installed, which causes System.Data.SQLite.Core to be installed as a dependency.

What I tried

I used the Dockerfile pre-assembled by Visual Studio 2022 which deals with all referenced projects:

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"]

Since this Dockerfile is based on a multi-stage build it has the following lines:

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

to first build the code, then publish it. Given dotnet publish I decided to be sure that I was able to publish the project myself, to narrow down the issue. Publishing locally also gave me problems, in particular the NU1605 error preventing to end the process. I resolved the issue using what Microsoft suggests. Now if I run the .exe located inside the publish destination folder, the application works as expected.

The image building process went well, but the "Unable..." -error appeared at runtime. To solve the SQLite.Interop.dll issue they suggest to move SQLite.Interop.dll in the bin folder; I found it inside bin\Release\netcoreapp3.1\runtimes, both in win-x86 and win-x64 sub-directories. I tried to publish the project locally in a folder with the following settings:

![enter image description here

This made SQLite.Interop.dll appear in the bin folder and got rid of the runtimes folder. To obtain the same result with Docker I modified the Dockerfile like this:

...
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 appears in the bin folder in the Docker running container, so I thought everything was fine, but still got the exception.

One last thing

Running the application locally (not in Docker) without specifying the destination runtime (keeping the build process as "Any CPU" instead of x64), raised no exceptions (that is, keeping the runtimes/ folder and the two SQLite.Interop.dll files inside of it in the win-x86 and win-x64 sub-folders).

Upvotes: 5

Views: 2036

Answers (3)

carlos357
carlos357

Reputation: 449

I was getting the same error and was able to fix it downgrading SQLite to 1.0.113. It seems that this error was introduced in Sqlite version 1.0.115. See here:

https://sqlite.org/forum/info/f80d7580fc07ce5c

I was using .net 8 and sqlite 1.0.119. On the development computer it was working just fine but when deployed on an container (windows nano server ltsc 2019) I got that error.

So I downgraded the SQLite package version on my Visual Studio project to 1.0.113.0. But note that it is not available directly in the nuget package repository. You have to download it from the Sqlite website:

https://system.data.sqlite.org/blobs/1.0.113.0/Stub.System.Data.SQLite.Core.NetStandard.1.0.113.0.nupkg

And then, under Visual Studio add a folder where this file is located (anywhere, in my case the project folder) as a local package repository (right-click on the project -> Manage NuGet Packages -> click on the wheel at the top right -> Package sources -> click on "+" -> set the path below. done

Upvotes: 0

Konstantin Volynskiy
Konstantin Volynskiy

Reputation: 101

We have experienced the issue updating from System.Data.SQLite.Core 1.0.113.6 to 1.0.117.

Locally and in build pipeline everything works fine, but as soon as our app deployed in a docker container running mcr.microsoft.com/dotnet/runtime:6.0-nanoserver-1809 image - application throws the named exception Unable to load DLL 'SQLite.Interop.dll': The specified module could not be found.

I found this thread at sqlite forum which clarified the situation a bit: https://sqlite.org/forum/info/0c471ca86ae7a836

Quote from the forum:

This actually seems to be caused by some extra dependencies in the latest version of SQLite.Interop.dll.

Using dumpbin I compared the dependencies between version 1.0.113.7 and 1.0.114.4 and these new dependencies were added:

mscoree.dll
         1801473F0 Import Address Table
         180186090 Import Name Table
                 0 time date stamp
                 0 Index of first forwarder reference

                      6F StrongNameSignatureVerificationEx
                      71 StrongNameTokenFromAssembly
                      62 StrongNameFreeBuffer
                       F CorBindToRuntimeEx
                      61 StrongNameErrorInfo

WINTRUST.dll
         1801473E0 Import Address Table
         180186080 Import Name Table
                 0 time date stamp
                 0 Index of first forwarder reference

                      82 WinVerifyTrust 

mscoree.dll is not available in in the mcr.microsoft.com/dotnet/core/runtime image I was using. If I copy it in from a different image, SQLite.Interop.dll is loaded successfully

We ended up reverting back to version 1.0.113.6 as we didn't want to introduce extra complexity to docker image. I hope the issue with the latest System.Data.SQLite.Core will be resolved in one of the coming versions.

Upvotes: 2

harry
harry

Reputation: 702

Solution

To run a dotnet application (e.g. dotnet test) inside a windows docker container with the System.Data.SQLite.Core nuget package you can use the following docker file

# 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 

Here is the releveant part of my csproj file:

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

What worked for me

After switching to the script method, to install the .NET framework (and not using the binary) it worked for me.

Beforehand, like you, I tried a ton of different things!

What you can try

What might work is also to add the PrivateAssets="none" in the csproi. See this answer. After adding this to the csproj files I got a different error, because I must use a x86-dll in my project.

After installing .NET 6 x86 correctly, I reverted even this change in the csproj and it still worked!

What else

What I also tried, but was not necessary in the end, was Microsoft Visual C++ Runtime Library.

Quote from https://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki

All downloadable packages on this web page that do not include the word "static" in their file name require the appropriate version (e.g. 2005, 2008, 2010, 2012, 2013, 2015, 2017) of the Microsoft Visual C++ Runtime Library, to be successfully installed on the target machine, prior to making use of the executables contained therein.

...
# 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;

More information on How-To install .NET in a docker container can be found at the dotnet-docker github repo

TL/DR

Use dotnet-install.ps1 in your dockerfile to install .NET and the SDK. Somehow, it does some magic, so that you can run dotnet apps which are using the SQLite.Interop.dll library (included via nuget)

Upvotes: 1

Related Questions