System.DllNotFoundException: Unable to load shared library 'gdiplus.dll' or one of its dependencies. ..., wrapped in The type initializer for 'Windows.Win32.PInvoke' threw an exception, is what new Bitmap(10, 10) from System.Drawing.Common 9.0.0 gave on the Linux runtime:10.0 image. The tested way out was to draw with SkiaSharp instead.

The expected message, System.Drawing.Common is not supported on this platform, did not appear in this test. The failure was a missing Windows library instead, and the post is about that output.

The error

PS> docker run --rm --name fix10-dn-d1 fix10-dn-lab drawing
Unhandled exception. System.TypeInitializationException: The type initializer for 'Windows.Win32.PInvoke' threw an exception.
 ---> System.TypeInitializationException: The type initializer for 'System.Drawing.Gdip' threw an exception.
 ---> System.TypeInitializationException: The type initializer for 'Windows.Win32.Graphics.GdiPlus.GdiPlusInitialization' threw an exception.
 ---> System.DllNotFoundException: Unable to load shared library 'gdiplus.dll' or one of its dependencies. In order to help diagnose loading problems, consider using a tool like strace. If you're using glibc, consider setting the LD_DEBUG environment variable:
/usr/share/dotnet/shared/Microsoft.NETCore.App/10.0.13/gdiplus.dll.so: cannot open shared object file: No such file or directory
/usr/share/dotnet/shared/Microsoft.NETCore.App/10.0.13/libgdiplus.dll.so: cannot open shared object file: No such file or directory
/usr/share/dotnet/shared/Microsoft.NETCore.App/10.0.13/gdiplus.dll: cannot open shared object file: No such file or directory
/usr/share/dotnet/shared/Microsoft.NETCore.App/10.0.13/libgdiplus.dll: cannot open shared object file: No such file or directory
...
   at System.Drawing.Bitmap..ctor(Int32 width, Int32 height)
   at Program.<Main>$(String[] args) in /src/Program.cs:line 22

Why it happens

The innermost exception is the cause: the Bitmap constructor went through System.Drawing.Gdip, which tried to load gdiplus.dll, and the runtime looked for it under four names in the runtime folder and found none: the Linux image has no file under any of those names. The outer TypeInitializationException layers are the static constructors that failed on the way, which is why the top line names Windows.Win32.PInvoke rather than anything you wrote.

The project compiled with the CA1416 platform warning switched off in the project file (<NoWarn>CA1416</NoWarn>). A full build without -q printed only NU1902 and NU1903 warnings for System.Security.Cryptography.Pkcs 9.0.4 and no warning that named System.Drawing; the image built and the crash came at the first Bitmap.

The fix

No change to the image was tested for System.Drawing.Common. What was tested is replacing the call with SkiaSharp 3.119.0 plus its Linux native assets, on the same runtime:10.0 base:

using var bmp = new SkiaSharp.SKBitmap(10, 10);
Console.WriteLine($"SKBitmap {bmp.Width}x{bmp.Height}");
RUN dotnet add package SkiaSharp.NativeAssets.Linux.NoDependencies --version 3.119.0
PS> docker run --rm --name fix10-dn-s2 fix10-dn-lab-skiafix skia
SKBitmap 10x10

This is a code change, not a package swap: SKBitmap is a different type from Bitmap, so every drawing call has to be rewritten against the SkiaSharp API. Only the 10 by 10 bitmap above was tested. The native assets package is not optional: without it SkiaSharp fails on Linux with its own DllNotFoundException, covered in the post linked below.

How it was reproduced

A console app referencing System.Drawing.Common 9.0.0, built on mcr.microsoft.com/dotnet/sdk:10.0 (SDK 10.0.302) and run on mcr.microsoft.com/dotnet/runtime:10.0 (Microsoft.NETCore.App 10.0.13), whose drawing mode creates a 10 by 10 Bitmap. Docker engine 29.9.3 on Windows 11. No other System.Drawing.Common version was tried.

Frequently asked

Does System.Drawing.Common work in a Linux Docker container?
Not in this test. System.Drawing.Common 9.0.0 on runtime:10.0 failed at new Bitmap(10, 10) with DllNotFoundException for gdiplus.dll inside several TypeInitializationException layers.
What can I use instead of System.Drawing in a .NET Linux container?
SkiaSharp worked in the test: SkiaSharp 3.119.0 with SkiaSharp.NativeAssets.Linux.NoDependencies 3.119.0 created an SKBitmap on runtime:10.0.
Why does the error mention Windows.Win32.PInvoke?
That is the outermost static constructor that failed. The real cause is the innermost exception, which says gdiplus.dll could not be loaded.

The SkiaSharp side: Unable to load shared library 'libSkiaSharp'. More decoded errors in the Fixes category.