linuxdocker.net-6.0alpine-linuxskiasharp

Deploy SkiaSharp on a container running .NET 6 Alpine Linux


SkiaSharp fails at runtime when deployed to an alpine linux container, using .NET 6.0 with the following error:

System.TypeInitializationException: The type initializer for 'SkiaSharp.SKImageInfo' threw an exception. ---> System.DllNotFoundException: Unable to load shared library 'libSkiaSharp' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: liblibSkiaSharp: cannot open shared object file: No such file or directory at SkiaSharp.SkiaApi.sk_colortype_get_default_8888() at SkiaSharp.SKImageInfo..cctor() --- End of inner exception stack trace --- at ZXing.SkiaSharp.Rendering.SKBitmapRenderer.Render(BitMatrix matrix, BarcodeFormat format, String content, EncodingOptions options) at ZXing.BarcodeWriter`1.Write(String contents)

I have tried (with no effect)

Project file

  <ItemGroup>
    <PackageReference Include="SkiaSharp" Version="2.80.3" />
    <PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="2.80.3" />
    ...
  </ItemGroup>

My current Dockerfile (simplified)

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

FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build
WORKDIR /src
COPY . .
WORKDIR "/src/Web"
RUN dotnet build "Web.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "Web.csproj" -c Release -o /app/publish -r alpine-x64 --no-self-contained

FROM base AS final
RUN apt-get update \
    && apt-get install -y libfontconfig1 fontconfig \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* \
    && export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/app/publish/
WORKDIR /app
COPY --from=publish /app/publish .
COPY --from=publish /app/publish/libSkiaSharp.so /usr/lib/
ENV ASPNETCORE_URLS=http://*:5000 
ENTRYPOINT ["dotnet", "Web.dll"]

Any help would be appreciated.

Update: Working Solution Thanks @omajid

FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine AS base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build
WORKDIR /src
COPY . .
WORKDIR "/src/Web"
RUN dotnet build "Web.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "Web.csproj" -c Release -o /app/publish -r linux-musl-x64 --no-self-contained

FROM base AS final
RUN apk update \
    && apk --no-cache add icu-libs fontconfig ttf-dejavu
WORKDIR /app
COPY --from=publish /app/publish .
ENV ASPNETCORE_URLS=http://*:5000 
ENV DOTNET_RUNNING_IN_CONTAINER=true
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
ENTRYPOINT ["dotnet", "Web.dll"]

Solution

  • You are targeting your application for alpine, but you are running it in the final container, which is based on base:

    FROM base AS final
    

    And base is just

    FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
    

    And that's a Debian 11 image:

    $ podman run -it mcr.microsoft.com/dotnet/aspnet:6.0 /bin/bash
    root@61566364141c:/# cat /etc/os-release 
    PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
    NAME="Debian GNU/Linux"
    VERSION_ID="11"
    VERSION="11 (bullseye)"
    VERSION_CODENAME=bullseye
    ID=debian
    HOME_URL="https://www.debian.org/"
    SUPPORT_URL="https://www.debian.org/support"
    BUG_REPORT_URL="https://bugs.debian.org/"
    

    So, you probably want to switch the base container to alpine before running it? Alternatively, target linux-x64 instead of alpine-x64?

    Also, Microsoft's recommendation is to use generic RIDs (eg, linux-musl-x64, or linux-arm64) instead of specific ones (eg alpine-x64 or rhel.8-arm64).