Laden...

AspNetCore in Docker-Umgebung: Fehlende DLL- und Resourcendateien

Erstellt von emuuu vor 5 Jahren Letzter Beitrag vor 5 Jahren 1.902 Views
emuuu Themenstarter:in
286 Beiträge seit 2011
vor 5 Jahren
AspNetCore in Docker-Umgebung: Fehlende DLL- und Resourcendateien

Guten Tag zusammen,

ich habe mal eine frage bezüglich der Vorbereitung eines Projekts für die Veröffentlichung in Docker. Ich versuche gerade meinen IdentityServer in einen Docker-Container zu verfrachten. Das funktioniert im Prinzip auch soweit, die Login-Seite ist von außerhalb erreichbar.
Was mir nun als erstes auffällt, ist dass alle meine Lokalisierungen fehlen. Sprich überall stehen nur die Platzhaltertexte nicht die tatsächliche Lokalisierung (siehe Bild).

Des Weiteren funktioniert der Login nicht, da scheinbar die Bibliothek fehlt mit der ich die Passwörter hashe:> Fehlermeldung:

fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.DllNotFoundException: Unable to load DLL 'libsodium' or one of its dependencies: The specified module could not be found. (Exception from HRESULT: 0x8007007E)
at Sodium.SodiumLibrary.crypto_pwhash_str_verify(Byte[] buffer, Byte[] password, Int64 passLength)
at Sodium.PasswordHash.ArgonHashStringVerify(Byte[] hash, Byte[] password)

Also scheinbar werden die entsprechende Dateien nicht mit ins Image respektive den Container geladen. Was ich nicht ganz verstehen kann, da zumindest der Password-Hasher von NuGet kommt und ich im Dockerfile dotnet restore ausführe.

Anbei das Dockerfile:


FROM microsoft/dotnet:2.1-aspnetcore-runtime-nanoserver-sac2016 AS base
WORKDIR /app
EXPOSE 5000

FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY FM.Iniquitas.Authentication/FM.Iniquitas.Authentication.csproj FM.Iniquitas.Authentication/
COPY FM.Iniquitas.Options/FM.Iniquitas.Options.csproj FM.Iniquitas.Options/
COPY FM.Iniquitas/FM.Iniquitas.csproj FM.Iniquitas/
COPY FM.Iniquitas.DataAccess.Dapper.Mssql/FM.Iniquitas.DataAccess.Dapper.Mssql.csproj FM.Iniquitas.DataAccess.Dapper.Mssql/
COPY FM.Iniquitas.DataAccess/FM.Iniquitas.DataAccess.csproj FM.Iniquitas.DataAccess/
COPY FM.Iniquitas.DataAccess.Dapper/FM.Iniquitas.DataAccess.Dapper.csproj FM.Iniquitas.DataAccess.Dapper/
RUN dotnet restore FM.Iniquitas.Authentication/FM.Iniquitas.Authentication.csproj
COPY . .
WORKDIR /src/FM.Iniquitas.Authentication
RUN dotnet build FM.Iniquitas.Authentication.csproj -c Release -o /app

FROM build AS publish
RUN dotnet publish FM.Iniquitas.Authentication.csproj -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .


ENTRYPOINT ["dotnet", "FM.Iniquitas.Authentication.dll"]

Imho müssten dotnet publish doch dafür sorgen, dass alles Notwendige in den Container kopiert wird oder?

Beste Grüße
emuuu

2+2=5( (für extrem große Werte von 2)

16.807 Beiträge seit 2008
vor 5 Jahren

Das liegt i.d.R. daran, dass Dir Referenzen für das Hosting fehlen.

Wenn Du nicht Microsoft.AspNetCore.All verwendest, dann musst Du die Hosting Referenz von Hand in das Projekt packen (über NuGet)
Publish ist dafür nicht verantwortlich, da es Deine Hosting Umgebung nicht kennen kann - und vor allem ist .NET nicht verantwortlich für Shadow Copies von unmanaged dlls.

Hatte den Fall erst gestern, dass mir eine ähnliche Datei (nicht die selbe) gefehlt hatte, weil ich nicht auf Microsoft.AspNetCore.All verwiesen habe, sondern auf *.App.

PS: Warum basiert Dein Base Image auf Windows Nano Server und das SDK auf Linux?
Sowas sollte man ja vermeiden.

emuuu Themenstarter:in
286 Beiträge seit 2011
vor 5 Jahren

Wenn Du nicht Microsoft.AspNetCore.All verwendest

Ich verwende Microsoft.AspNetCore.App (2.1.2)

dann musst Du die Hosting Referenz von Hand in das Projekt packen (über NuGet)

Wie ginge das? Mich wundert vor allem das Problem mit der Lokalisierung
Im Projekt hab ich einfach folgende Datei:
Resources/Views/Account/Login.de-DE.resx
Dotnet publish erstellt dann im Workdir den Ordner de-DE mit der entsprechenden Resources.dll, ich wüsste jetzt nicht wie/wo ich die noch separat referenzieren könnte.

PS: Warum basiert Dein Base Image auf Windows Nano Server und das SDK auf Linux?

Danke für den Hinweis, habe so viel mit den Base-Images rumgespielt (mein anderes Problem bezüglich Zertifikat-Import), da ist mir das gar nicht aufgefallen.

2+2=5( (für extrem große Werte von 2)

16.807 Beiträge seit 2008
vor 5 Jahren

Wenn Du nicht Microsoft.AspNetCore.All verwendest
Ich verwende Microsoft.AspNetCore.App (2.1.2)

App ist nicht All.

emuuu Themenstarter:in
286 Beiträge seit 2011
vor 5 Jahren

Aber App ist doch wenn ich das richtig lese entsprechend All ausgenommen der in der Migrationsanleitung genannten Pakete?

Wie gesagt ich verstehe nicht, wo mir eine Referenz fehlt:

  <ItemGroup>
    <PackageReference Include="IdentityServer4" Version="2.2.0" />
    <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.6.0" />
    <PackageReference Include="IdentityServer4.AspNetIdentity" Version="2.1.0" />
    <PackageReference Include="IdentityServer4.EntityFramework" Version="2.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Localization" Version="2.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.1.1" />
    <PackageReference Include="MailKit" Version="2.0.5" />
    <PackageReference Include="ScottBrady91.AspNetCore.Identity.Argon2PasswordHasher" Version="1.0.0" />
    <PackageReference Include="Serilog.Extensions.Logging" Version="2.0.2" />
    <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
    <PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.0" />
  </ItemGroup>

Mit "Microsoft.AspNetCore.Mvc.Localization" und "ScottBrady91.AspNetCore.Identity.Argon2PasswordHasher" müsste ich doch genau die beiden Pakete referenziert haben (die scheinbar nicht funktionieren) unabhängig ob *.All oder *.App. Oder verstehe ich das falsch?

2+2=5( (für extrem große Werte von 2)

16.807 Beiträge seit 2008
vor 5 Jahren

Hast Dir denn überhaupt mal angeschaut, in welchem Paket libsodium drin sein sollte?
Vermutlich nicht. Du ratest eher - jedenfalls liest sich das so.

Hab jetzt einfach mal "ScottBrady91.AspNetCore.Identity.Argon2PasswordHasher" gegoogelt und gesehen, dass es Teil dieses Pakets ist.
Das wäre eigentlich Deine Aufgabe gewesen, das zu lokalisieren.

Jetzt kannst Dir anschauen, warum die libsodium nicht mit kommt.
Publish ist jedenfalls prinzipiell nicht dafür verantwortlich, dass unmanaged DLLs mit im Paket landen.

Das sollte eigentlich beim Restore des Pakets passieren.

Exportiere Dir den Docker Container als TAR, öffne ihn mit zB. Winrar und schau Dir an, was tatsächlich im Container landet - und wo es liegt.

PS: Dein Docker File wird so nicht funktionieren, wenn Du einen private NuGet Feed hast.
Es ist aktuell nicht (sicher) möglich Credentials in den Build Prozess zu bringen.

emuuu Themenstarter:in
286 Beiträge seit 2011
vor 5 Jahren

Hab jetzt einfach mal "ScottBrady91.AspNetCore.Identity.Argon2PasswordHasher" gegoogelt und gesehen, dass es Teil dieses Pakets ist.
Das wäre eigentlich Deine Aufgabe gewesen, das zu lokalisieren.

Ich kann deinen Angriff insofern nicht nachvollziehen, da ich direkt gesagt habe, dass der PasswordHasher das Problem ist (der natürlich die libsodium.dll enthält), das steht doch schon in der StackTrace.

Ich verstehe auch insofern nicht, was du mit privaten Nuget-Feeds hast, da ich ausschließlich die oben genannten public Pakete verwende.

Die dll ist im Container 4x vorhanden jeweils in der linux, osx, win64 & win86 runtime:
C:\app\runtimes\win-x64\native\libsodium.dll
C:\app\runtimes\win-x86\native\libsodium.dll

Und da bin ich wieder am Anfang, weil ich nicht verstehe warum, trotz der offensichtlich vorhandenen DLL ein Fehler auftritt. Denn in exakt dem gleichen Ordner liegt die DLL wenn ich das ganze z.B. auf einen IIS publishe. Und dort funktioniert es.

2+2=5( (für extrem große Werte von 2)

16.807 Beiträge seit 2008
vor 5 Jahren

da ich direkt gesagt habe, dass der PasswordHasher das Problem ist

Du hast immer wieder die Localization ins Spiel gebracht.

Ich verstehe auch insofern nicht, was du mit privaten Nuget-Feeds hast

War ein Hinweis, falls Du es benötigst. 👍

Und da bin ich wieder am Anfang, weil ich nicht verstehe warum, trotz der offensichtlich vorhandenen DLL ein Fehler auftritt.

Bitte les die Fehlermeldung komplett:

> System.DllNotFoundException: Unable to load DLL 'libsodium' or one of its dependencies

Du hast also geprüft, dass die DLL dort liegt, wo sie Dein Paket erwartet?
Du hast also geprüft, dass alle Abhängigkeiten der DLL (inkl. unmanaged) dort liegen, wo die DLL sie erwartet?

DAS bezweifle ich - sonst würde die Fehlermeldung nicht kommen. 😉
Sie kommt nicht umsonst.

Erster Google Treffer nach identischer Fehlermeldung besagt:

It turns out that ASP.NET doesn't make shadow copies of unmanaged DLLs such as libsodium.dll and libsodium-64.dll.

Sodium.dll (the managed code) tries to load the DLLs from either the same directory as the shadow copy of Sodium.dll (which is not going to work) - or some where in the PATH environment variable's directories.

Hab Dir ja jetzt mehrfach gesagt, dass Publish pauschal nicht unbedingt unmanaged stuff mitpackt - und dafür auch nicht verantwortlich ist.

Im einfachsten Fall ist bereits alles da, aber ASP.NET Core findet es nicht weil die Info ders Working Directory fehlt.
In IIS bekommst Du das durch die Pipeline injiziert, in Docker nicht.

emuuu Themenstarter:in
286 Beiträge seit 2011
vor 5 Jahren

Erster
>
besagt

Auf besagten Thread bin ich bereits bevor ich hier gepostet habe gestoßen. Leider führt der Ansatz dort (auch nach Installation von Visual C++2015) zu keinem anderen Ergebnis.

Nachdem ich nun genug Zeit darauf verschwendet habe, hab ich zu einem BCrypt-Hasher gewechselt, der ohne unmanaged Dlls auskommt.

2+2=5( (für extrem große Werte von 2)