Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SkiaSharp does not work in Docker Windows Container. #591

Closed
AlexNosk opened this issue Jul 25, 2018 · 23 comments
Closed

SkiaSharp does not work in Docker Windows Container. #591

AlexNosk opened this issue Jul 25, 2018 · 23 comments
Milestone

Comments

@AlexNosk
Copy link

AlexNosk commented Jul 25, 2018

Description

SkiaSharp throws when run in Windows container.

Code

Steps to reproduce:

  1. Create a simple Console application that uses SkiaSharp

using SkiaSharp;
using System;

namespace SkiaSharpDockerTest
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Environment.OSVersion);

       try
       {
           using (SKBitmap bmp = new SKBitmap(100, 100))
           using (SKCanvas canvas = new SKCanvas(bmp))
           using (SKPaint p = new SKPaint())
           {
               p.Color = SKColors.Red;
               canvas.DrawCircle(50, 50, 50, p);

               using (SKFileWStream fs = new SKFileWStream("out.png"))
                   bmp.Encode(fs, SKEncodedImageFormat.Png, 100);
           }
       }
       catch (Exception ex)
       {
           Console.WriteLine(ex.Message);
           Console.WriteLine(ex.StackTrace);
       }

}
}

  1. Create a Dokerfile

FROM microsoft/dotnet:2.0-sdk
WORKDIR /app
COPY . ./
RUN dotnet publish -c Release -o out
ENTRYPOINT ["dotnet", "out/SkiaSharpDockerTest.dll"]

  1. Build and run image

docker build -t skiasharptest .
docker run --rm skiasharptest SkiaSharpDockerTest from Docker

As a result exception is thrown
The type initializer for 'SkiaSharp.SKImageInfo' threw an exception.
at SkiaSharp.SKBitmap..ctor(Int32 width, Int32 height, Boolean isOpaque)
at AsposeWordsDockerTest.Program.Main(String[] args) in C:\app\Program.cs:line 15

Expected Behavior

Red circle image should be created

Actual Behavior

throws an exception

Basic Information

  • Version with issue: 1.60.2
  • Last known good version: none
  • IDE: Visual Studio
  • Platform Target Frameworks: .NET Core 2.0
  • Target Devices: Docker Windows container
@AlexNosk
Copy link
Author

Any update on this?

@kekekeks
Copy link
Contributor

kekekeks commented Oct 2, 2018

@AlexNosk

You are probably missing Visual C++ runtime. See #136

@chrismellard
Copy link

@kekekeks This is one issue with running SkiaSharp inside Windows containers but not the only one. libSkiaSharp.dll also has a dependency on both opengl32.dll and glu32.dll.

@AlexNosk In your dockerfile copy these two assemblies in to the windows/system32 folder and things work fine - least they did for me. This is a hack, and so long as you don't any of whatever skiasharp requires from those libraries to actually work you're all good. I think they're working on 3d support for windows containers at the moment.

@kekekeks
Copy link
Contributor

kekekeks commented Oct 3, 2018

On Linux opengl references are resolved dynamically. See mono/skia#50 and
mono/skia@b579390

I guess on Windows we can do the same.

@mattleibow
Copy link
Contributor

@kekekeks I am thinking that maybe we should - it appears that those assemblies are not always distributed on some "versions"... What are they actually? @chrismellard what container were you using? I thought they were always part of all Windows.

@chrismellard
Copy link

@mattleibow Container I had to copy those libraries in from was

FROM microsoft/iis:windowsservercore-1803

@mattleibow
Copy link
Contributor

Thanks. I will investigate.

@mattleibow
Copy link
Contributor

mattleibow commented Oct 5, 2018

Hmm. I see opengl32.dll is already dynamically loaded:
https://github.com/google/skia/blob/36f7e3298e9d8e21d095197db0ec72c155f7d61f/src/gpu/gl/win/GrGLMakeNativeInterface_win.cpp
(this is untrue 😞)

@mattleibow
Copy link
Contributor

mattleibow commented Oct 6, 2018

After that commit, the new dependency tree is basically:

  • fontsub.dll
  • ole32.dll
  • user32.dll
  • kernel32.dll
  • msvcp140.dll (vcredist)
  • vcruntime140.dll (vcredist)

deps

I am also working on making sure that there is an easy path for Docker. I have managed to basically get this working:

RUN Invoke-WebRequest -OutFile vc_redist.x64.exe https://aka.ms/vs/15/release/vc_redist.x64.exe `
    Start-Process vc_redist.x64.exe -ArgumentList '/install /passive /norestart' -Wait

I will be creating a wiki with all the steps for creating a Docker container for both Windows and Linux.

Right now, nanoserver is not playing nice and several dependencies are missing, so I don't think that support will be coming soon, but it will work fine with windowsservercore variants.

@kekekeks
Copy link
Contributor

kekekeks commented Oct 6, 2018

May be it's time to reconsider about static CRT linking? It doesn't increase binary size that much, but decreases surprise factor by a lot.

@mattleibow
Copy link
Contributor

mattleibow commented Oct 6, 2018

Having a look at Nano Server... Ran the NanoServerApiScan.exe tool from: https://blogs.technet.microsoft.com/nanoserver/2016/04/27/nanoserverapiscan-exe-updated-for-tp5/

=== libSkiaSharp.dll ===

ERRORS:

  FONTSUB.dll
    CreateFontPackage(Proc not found)
  USER32.dll
    SystemParametersInfoW(Proc not found)
  MSVCP140.dll
    …
    …
    …
      Please copy Nano Server compliant MSVCP140.dll from %ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\redist\onecore\x64\Microsoft.VC140.CRT\
  VCRUNTIME140.dll
    …
    …
    …
      Please copy Nano Server compliant VCRUNTIME140.dll from %ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\redist\onecore\x64\Microsoft.VC140.CRT\

I need to investigate the 2 usages that appear to be bad:

  • FONTSUB.dll (CreateFontPackage)
  • USER32.dll (SystemParametersInfoW)

@mattleibow
Copy link
Contributor

Just did some investigation :)

CreateFontPackage from FONTSUB.dll is just for XPS support - and this is also just for font subsetting. The UWP build does not have this at all, so I could just remove it for a nano build.

SystemParametersInfoW from USER32.dll is also not too essential - it is just for determining the default font. Again, this is not available for UWP - we just pick the "Segoe UI" which we know is available by default.

Nano Server support could very well be possible in the near future - just have to check priorities.

@mattleibow
Copy link
Contributor

@kekekeks I have been thinking about this and I will link in #136 so we can keep the discussion linked, but that discussion should be done there. (going to make a comment there now)

@mattleibow
Copy link
Contributor

Closing this as I have done a few things:

I have opened a new issue to support Nano server: #676

@mattleibow
Copy link
Contributor

Nano server images are now supported after #1040

@mattleibow
Copy link
Contributor

Just linking this new issue : NuGet/Home#8894

@mattleibow mattleibow added this to the v1.68.1.1 milestone Dec 19, 2019
@djarvis
Copy link

djarvis commented Feb 14, 2020

I ended up here because of some confusion over SkiaSharp in a NanoServer docker container. While I was able to get some things working after including SkiaSharp.NativeAssets.NanoServer, I noticed that I cannot draw text onto a bitmap using a font that I load from a file:

var typeFace = SKTypeface.FromFile("Font Awesome 5 Free-Solid-900.otf");
var paint = new SKPaint() { TextSize = 40, Color = SKColor.Parse("FF0000"), Typeface = typeFace};
SKRect bounds = new SKRect();
paint.MeasureText(unicodeCharacter, ref bounds);

bounds is always 0x0.

I see that SkiaSharp.NativeAssets.NanoServer shows:

This variation of the Windows native assets includes the build of libSkiaSharp.dll that does not make use of the typeface subsetting when creating XPS documents (CreateFontPackage from FONTSUB.dll).

So I'm guessing this has to do with something.

Is there any way to use a font in NanoServer?

@Gillibald
Copy link
Contributor

Unfortunately there is currently no support for text rendering on Nano Server. That will most likely change with the next major release of SkiaSharp when Freetype can be used for Windows builds.

@mattleibow
Copy link
Contributor

@djarvis as @Gillibald says, there is currently an issue #1105

For now, is it possible to use the Linux images? Typically they are smaller and just as good. And, if you have a Windows host, they can be run side-by-side with Windows containers. That is the best for now, or use a Windows Server Core image - like this example.

@djarvis
Copy link

djarvis commented Feb 15, 2020

@mattleibow We have been using solely Linux containers but now have to offer up Windows containers. I'd rather not have the 4.8GB footprint just to be able to draw a font onto a bitmap so I'd like to stick to the nanoserver images.

We need to support simple, single-machine deployments. With the need to run along side legacy Windows apps, we see Windows Server 2019 as a solution since it comes with a free Docker EE license and as of now LCOW is still in an unsupported preview. Otherwise we'd just continue with Linux containers.

I just need to draw this one font onto a bitmap so I might be able to take the svg and find a renderer and draw it manually but I haven't looked too far into that.

@Gillibald
Copy link
Contributor

You will be soon able to generate glyph outlines with the help of HarfBuzzSharp. Maybe thats a good way to get text rendered without having to rely on a font host implementation.

@djarvis
Copy link

djarvis commented Feb 17, 2020

Luckily since I just needed to draw the Font Awesome glyphs I was able to use SkiaSharp.Svg to draw the relatively simple svgs onto a bitmap
This seems to work on Linux and Windows.

@christian289
Copy link

christian289 commented Nov 16, 2021

Hello.
I am trying to use SkiaSharp in windows docker container.
My environment is below.

  • .NET 5.
  • Windows 10 Pro, 21H1, 19043.1348
  • Visual Studio 2019 Pro
  • SkiaSharp.NativeAsserts.Linux.NoDependencies 2.80.3

Below is a screenshot of the Docker desktop.
image

log

warn�]0;C:\Program Files\dotnet\dotnet.exe�warn: ImageAutoSliceBackgroundServiceForWindows.ImageAutoSliceWorker[0]
[11/16/2021 6:17:10 PM][ImageAutoSliceWorker]Input Message
System.TypeInitializationException: The type initializer for 'SkiaSharp.SKAbstractManagedStream' threw an exception.
---> System.DllNotFoundException: Unable to load DLL 'libSkiaSharp' or one of its dependencies: The specified module could not be found. (0x8007007E)
at SkiaSharp.SkiaApi.sk_managedstream_set_procs(SKManagedStreamDelegates procs)
at SkiaSharp.SKAbstractManagedStream..cctor()
--- End of inner exception stack trace ---
at SkiaSharp.SKAbstractManagedStream..ctor(Boolean owns)
at SkiaSharp.SKManagedStream..ctor(Stream managedStream, Boolean disposeManagedStream)
at ImageAutoSliceBackgroundServiceForWindows.ImageAutoSliceWorker.MakeSKBitmap(ReadOnlySpan`1 span) in C:\app\Workers\ImageAutoSliceWorker.cs:line 192
at ImageAutoSliceBackgroundServiceForWindows.ImageAutoSliceWorker.MessageHandler(ProcessMessageEventArgs args)
at Azure.Messaging.ServiceBus.ServiceBusProcessor.OnProcessMessageAsync(ProcessMessageEventArgs args)
at Azure.Messaging.ServiceBus.ReceiverManager.OnMessageHandler(ServiceBusReceivedMessage message, CancellationToken processorCancellationToken)
at Azure.Messaging.ServiceBus.ReceiverManager.ProcessOneMessage(ServiceBusReceivedMessage message, CancellationToken cancellationToken)

The above problem occurs when the first class related to SkiaSharp is called. The code to be called is as follows.

        private SKBitmap MakeSKBitmap(ReadOnlySpan<byte> span) // 189 line
        {
            MemoryStream ms = new(span.ToArray()); // 191 line
            SKManagedStream skStream = new(ms, false); 192 line, Exception Occured !!
            SKCodec codec = SKCodec.Create(skStream);

            return SKBitmap.Decode(codec);
        }

Dockerfile

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
SHELL ["pwsh", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
USER ContainerAdministrator
RUN Invoke-WebRequest https://raw.githubusercontent.com/microsoft/artifacts-credprovider/master/helpers/installcredprovider.ps1 -OutFile ./installcredprovider.ps1; 
RUN .\installcredprovider.ps1;
RUN del installcredprovider.ps1
USER ContainerUser
WORKDIR /app
COPY ["ImageAutoSliceBackgroundServiceForWindows.csproj", ""]
COPY ["nuget.config", ""]

ARG ID
ARG PAT
RUN dotnet restore

COPY . .
RUN dotnet build -c Release -o out --no-restorehttps://github.com/dotnet/dotnet-docker/issues/1649#issuecomment-581433906
RUN dotnet publish

FROM mcr.microsoft.com/dotnet/runtime:5.0 AS runtime
WORKDIR /app/
COPY --from=build /app/out .

COPY /app/runtimes/win-x64/native
ENTRYPOINT ["dotnet", "ImageAutoSliceBackgroundServiceForWindows.dll"]

nuget.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
    <add key="EcremmoceSDK" value="https://pkgs.dev.azure.com/ecremmoce/_packaging/EcremmoceSDK/nuget/v3/index.json" />
  </packageSources>
  <activePackageSource>
    <add key="All" value="(Aggregate source)" />
  </activePackageSource>
  <packageSourceCredentials>
    <EcremmoceSDK>
      <add key="Username" value="%ID%" />
      <add key="ClearTextPassword" value="%PAT%" />
    </EcremmoceSDK>
  </packageSourceCredentials>
</configuration>

If you look at dockerfile and nuget.config, there are parts that are slightly different from the basic contents. This is all part of linking Azure DevOps Artifact and PAT, so it doesn't seem like it has anything to do with SkiaSharp, but I share it nonetheless.

I used SkiaSharp when developing WPF in .NET 5. At that time, I developed using 'SkiaSharp.NativeAsserts.Linux.NoDependencies 2.80.3', and even MSIX packaging was successful. So, again, I tried the following to use it as a Windows Container.

But the results were not good.
What more can I do?

@ghost ghost locked as resolved and limited conversation to collaborators Aug 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants