puppeteer-sharp: Can't run Puppeteer Sharp in Docker

Description

I am not able to run Puppeteer Sharp in a Windows docker container. It gives an error while trying to launch chromium.

Complete minimal example reproducing the issue

            var options = new LaunchOptions
            {
                Headless = true
            };

            Console.WriteLine("Downloading chromium");
            await Downloader.CreateDefault().DownloadRevisionAsync(Downloader.DefaultRevision);

            Console.WriteLine("Navigating google");
            using (var browser = await Puppeteer.LaunchAsync(options, Downloader.DefaultRevision))
            using (var page = await browser.NewPageAsync())
            {
                await page.GoToAsync("http://www.google.com");

                Console.WriteLine("Generating PDF");
                await page.PdfAsync(Path.Combine(Directory.GetCurrentDirectory(), "google.pdf"));

                Console.WriteLine("Export completed");
                Console.ReadLine();
            }

Actual behavior:

Downloading chromium
Navigating google

Unhandled Exception: PuppeteerSharp.ChromeProcessException: Failed to create connection ---> PuppeteerSharp.ChromeProcessException: Failed to launch chrome!
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at PuppeteerSharp.Launcher.<LaunchAsync>d__16.MoveNext()
   --- End of inner exception stack trace ---
   at PuppeteerSharp.Launcher.<LaunchAsync>d__16.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at PuppeteerSharpTest.Program.<MainAsync>d__1.MoveNext() in C:\Users\xxx\source\repos\PuppeteerSharpTest\PuppeteerSharpTest\Program.cs:line 27
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at PuppeteerSharpTest.Program.Main(String[] args) in C:\Users\xxx\source\repos\PuppeteerSharpTest\PuppeteerSharpTest\Program.cs:line 13

Versions

Docker

Client:
 Version:      18.03.1-ce
 API version:  1.37
 Go version:   go1.9.5
 Git commit:   9ee9f40
 Built:        Thu Apr 26 07:12:48 2018
 OS/Arch:      windows/amd64
 Experimental: false
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.03.1-ce
  API version:  1.37 (minimum version 1.24)
  Go version:   go1.9.5
  Git commit:   9ee9f40
  Built:        Thu Apr 26 07:21:42 2018
  OS/Arch:      windows/amd64
  Experimental: false

Dotnet

.NET Command Line Tools (2.1.200)

Product Information:
 Version:            2.1.200
 Commit SHA-1 hash:  2edba8d7f1

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.15063
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.1.200\

Microsoft .NET Core Shared Framework Host

  Version  : 2.0.7
  Build    : 2d61d0b043915bc948ebf98836fefe9ba942be11

Additional Information

Publish

dotnet publish -o out

Dockerfile

FROM microsoft/aspnetcore
WORKDIR /app
COPY out/ .
ENTRYPOINT ["dotnet", "PuppeteerSharpTest.dll"]

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 2
  • Comments: 17 (5 by maintainers)

Most upvoted comments

For the record I was able to make it work just via:

RUN apt-get update && apt-get install -y xorg openbox libnss3 libasound2

(in my Dockerfile) and:

var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
    Headless = true,
    Args = new string[] { "--no-sandbox" }
});

in my launch code.

This is what I used in my dockerfile for installing the dependencies for chrome/puppeteer:

FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app

RUN apt-get update

RUN apt-get install -y wget unzip fontconfig locales gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget

and this is the code I used to warmup chrome:

public HeadlessChrome()
        {

            _options = new LaunchOptions
            {
                Headless = true,
                Args = new string[] { "--no-sandbox" }
            };
            DownloadChrome().ConfigureAwait(true).GetAwaiter().GetResult();
        }

        private async Task DownloadChrome()
        {
            BrowserFetcher browserFetcher = new BrowserFetcher();
            var folder = browserFetcher.DownloadsFolder;
            await browserFetcher.DownloadAsync(BrowserFetcher.DefaultRevision);

            if (System.Runtime.InteropServices.RuntimeInformation
                                   .IsOSPlatform(OSPlatform.Linux))
            {
                var path = Launcher.GetExecutablePath();
                Bash($"chmod 777 {path}");
            }
        }

        public void Bash(string cmd)
        {
            var escapedArgs = cmd.Replace("\"", "\\\"");

            var process = new Process()
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName = "/bin/bash",
                    Arguments = $"-c \"{escapedArgs}\"",
                    RedirectStandardOutput = true,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                }
            };
            process.Start();
            string result = process.StandardOutput.ReadToEnd();
            process.WaitForExit();
        }

The only “problem” I had so far is it didnt install some fonts for example calibri but i’m looking into that.

now aday. You need install these package. so this is the dockerfile need include

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim as runtime

RUN apt-get update && apt-get install -y libx11-6 libx11-xcb1 libatk1.0-0 libgtk-3-0 libcups2 libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxrandr2 libgbm1 libpango-1.0-0 libcairo2 libasound2 libxshmfence1 libnss3

You won’t be able to run Chrome inside docker. You’d need to use some solution like browserless.io. Check out this blog post http://www.hardkoded.com/blogs/azure-chrome-puppeteer-browserless

Im using puppeteer nugetpackage 1.9.0. I also had the same issue that browser couldn’t launch in my linux container. I added this line in my dockerfile and it fixed the problem for me:

apt-get install -y wget unzip fontconfig locales gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget

reference: https://hub.docker.com/r/browserless/chrome/

@DdannyB are you confirming that you managed to run pptr# on Docker? Would you mind sharing some dockerfile here?

I was able to get it running easily in docker linux. I had to set execute permissions after I downloaded.

await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
            if (IsLinux() || IsMacOs())
            {
                var path = Launcher.GetExecutablePath();
                Console.WriteLine($"Setting permissions: {path}");

                Exec($"chmod 777 {path}");
            }

@respel long story short, a Docker container doesn’t have all the dependencies a browser needs to run. You can try to make this like this https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md#running-puppeteer-in-docker or this https://github.com/c0b/chrome-in-docker

Let me know how it goes if you go that way.

You won’t be able to run Chrome inside docker.

@kblok, can you please explain(or give references) why this is so ? This is definitely possible for a linux container though.

now aday. You need install these package. so this is the dockerfile need include

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim as runtime

RUN apt-get update && apt-get install -y libx11-6 libx11-xcb1 libatk1.0-0 libgtk-3-0 libcups2 libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxrandr2 libgbm1 libpango-1.0-0 libcairo2 libasound2 libxshmfence1 libnss3

Update 2023 (.NET 7):

this solution worked under FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base, but I also needed

        var browser = await Puppeteer.LaunchAsync(new LaunchOptions
        {
            Args = new string[] { "--no-sandbox" }
        });

and PDFs started to generate