Solving Native Library Loading Issues for .NET Core on Alpine Linux
Andrew Lock walks through the real-world debugging process for a library loading failure on Alpine Linux when running older .NET Core apps, clearly explaining the steps and ultimate resolution.
Solving Native Library Loading Issues for .NET Core on Alpine Linux
Author: Andrew Lock
Introduction
Running .NET Core applications on different Linux distributions can sometimes lead to challenging native library loading issues. In this post, Andrew Lock details how he and his team investigated and resolved a problem with Microsoft.Data.Sqlite
failing to load libe_sqlite3
on Alpine Linux 3.17 with .NET Core 3.1 and .NET 5, by methodically debugging the runtime and system configuration.
The Problem
After upgrading their CI/testing images to alpine:3.17
to support .NET 10, the team encountered the following exception:
System.DllNotFoundException: Unable to load shared library 'e_sqlite3' or one of its dependencies
This only affected samples targeting netcoreapp3.1
and net5.0
using Microsoft.Data.Sqlite
.
Initial Investigation
- The same application worked correctly on
alpine:3.14
. The upgrade toalpine:3.17
caused the failure. - Running
ldd
on the library in question (libe_sqlite3.so
) confirmed the dependencies were present and not missing. - Tools such as
LD_DEBUG
andstrace
were used to gain more insight, but didn’t provide clear clues since the library was loaded by .NET at runtime, not as a dynamic dependency.
Working Solution
Manually setting LD_LIBRARY_PATH
to include the directory with libe_sqlite3.so
allowed the app to run successfully. This suggested the problem was not the library itself, but how .NET was resolving runtime IDs and searching for the correct native assets.
Root Cause Analysis
- Old versions of .NET (3.1, 5.0) do not recognize newer versions of Alpine Linux (like 3.17) for runtime identifier (RID) mapping.
- As a consequence, the runtime uses a fallback RID (e.g.,
linux-x64
), failing to find native libraries built forlinux-musl-x64
. - Support for Alpine 3.17+ RIDs was only officially added in .NET 6 and above.
- The root issue was a missing mapping from modern Alpine versions to
linux-musl-x64
in old .NET Core runtime code.
Permanent Fix
Set the environment variable DOTNET_RUNTIME_ID=linux-musl-x64
before launching the application. Example:
DOTNET_RUNTIME_ID=linux-musl-x64 dotnet Samples.Microsoft.Data.Sqlite.dll
Alternatively, ensure LD_LIBRARY_PATH
includes the directory containing the needed native library. For future-proofing, upgrade to .NET 7+ where these issues are resolved by default.
Summary
- The error arises from lack of support for new Alpine Linux RIDs in legacy .NET runtimes.
- Diagnostic commands like
ldd
,LD_DEBUG
, andstrace
help to isolate native library loading problems. - Setting
DOTNET_RUNTIME_ID
explicitly guides the .NET runtime to use the correct assets. - .NET 7 and newer include these fixes, but for older runtimes, setting the environment variable is essential.
For full details and troubleshooting steps, see the original post by Andrew Lock: Fixing an old .NET Core native library loading issue on Alpine.
This post appeared first on “Andrew Lock’s Blog”. Read the entire article here