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

Can't run Puppeteer Sharp in Docker #262

Closed
respel opened this issue May 28, 2018 · 18 comments
Closed

Can't run Puppeteer Sharp in Docker #262

respel opened this issue May 28, 2018 · 18 comments

Comments

@respel
Copy link

respel commented May 28, 2018

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"]
@kblok
Copy link
Member

kblok commented May 28, 2018

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

@kblok kblok closed this as completed May 28, 2018
@respel
Copy link
Author

respel commented May 28, 2018

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.

@kblok
Copy link
Member

kblok commented May 28, 2018

@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.

@respel
Copy link
Author

respel commented May 28, 2018

@kblok , thanks for the help but I need it specifically for a windows container.

@kblok
Copy link
Member

kblok commented May 28, 2018

I'll try to dig a little bit into it. It would be great to know how to support this.
But it's out if the scope of Puppeteer Sharp. It's a Chrome issue.

@youngcm2
Copy link

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}");
            }

@kblok
Copy link
Member

kblok commented Aug 14, 2018

So maybe #430 will fix this issue. Thanks @youngcm2

@DdannyB
Copy link

DdannyB commented Nov 9, 2018

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/

@kblok
Copy link
Member

kblok commented Nov 9, 2018

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

@DdannyB
Copy link

DdannyB commented Nov 9, 2018

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.

@PavelShalahai
Copy link

PavelShalahai commented Jan 13, 2019

public HeadlessChrome()
{

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

Can you please tell me, is it works with Headfull in the container? Like Headless = false;
Thanks!

@DdannyB
Copy link

DdannyB commented Jan 14, 2019

I don't know for sure but my guess would be it would still work, I think it would only be a difference in performance because when headless is true it will not launch a full version of a browser.

This is a quote I found:
Turn off headless mode - sometimes it's useful to see what the browser is displaying. Instead of launching in headless mode, launch a full version of the browser using headless: false

i haven't tested it so i don't know for sure!

@shoe-diamente
Copy link

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.

@tommydangdn95
Copy link

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

@michalgrzyska
Copy link

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

@MSaqib-Rocket
Copy link

using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = false,
ExecutablePath = "D:\Saqib\Downloads\chrome-win\chrome.exe",
Args = new[] { "--disable-blink-features=AutomationControlled" }

    });

While building the image there is no issue in cmd but when I run the image then a issue is raised that shows

Unhandled exception. System.ComponentModel.Win32Exception (2): An error occurred trying to start process 'D:\Saqib\Downloads\chrome-win\chrome.exe' with working directory '/'. No such file or directory

//My Docker file
FROM mcr.microsoft.com/dotnet/runtime:6.0

Install dependencies

RUN apt-get update && apt-get install -y wget

Install Node.js and npm

RUN apt-get install -y curl
RUN curl -fsSL https://deb.nodesource.com/setup_14.x | bash -
RUN apt-get install -y nodejs

Install Google Chrome

RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
RUN apt-get install -y fonts-liberation libasound2 libatk-bridge2.0-0 libatk1.0-0 libatspi2.0-0 libcairo2 libcups2 libcurl4 libdbus-1-3 libdrm2 libexpat1 libgbm1 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libu2f-udev libvulkan1 libx11-6 libxcb1 libxcomposite1 libxdamage1 libxext6 libxfixes3 libxkbcommon0 libxrandr2 xdg-utils
RUN dpkg -i google-chrome-stable_current_amd64.deb

Install Puppeteer

RUN npm init -y
RUN npm i puppeteer

Add a user so you don't need --no-sandbox

RUN groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser
RUN mkdir -p /home/pptruser/Downloads
RUN chown -R pptruser:pptruser /home/pptruser
RUN chown -R pptruser:pptruser /node_modules
RUN chown -R pptruser:pptruser /package.json
RUN chown -R pptruser:pptruser /package-lock.json

Copy your application files

COPY bin/Release/net6.0/publish .

Set the entry point for your application

ENTRYPOINT ["dotnet", "PupeeterSharpGmailAutomation.dll"]

Q: Can anyone tell me how to solve it?
PS: I am using console app for the automation using puppeteer sharp.

@mammadovnihad
Copy link

mammadovnihad commented Nov 10, 2023

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

If you're using Azure App Service for Linux (Built-in images) without a custom Docker image, you can specify this as the Startup Command like:

sudo apt-get update && \
sudo 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 && \
 dotnet path/Project.dll

Azure Portal ref:

enter-startup-file-for-app-service-in-the-azure-portal

@dev-dilan
Copy link

dev-dilan commented Feb 12, 2024

Args = new string[] { "--no-sandbox" } worked for me both linux and windows

await new BrowserFetcher().DownloadAsync();
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
Args = new string[] { "--no-sandbox" }
});
var page = await browser.NewPageAsync();
string htmlFilePath = AppContext.BaseDirectory+"\test.html";
string htmlContent = File.ReadAllText(htmlFilePath);
await page.SetContentAsync(htmlContent);
var pdfOptions = new PdfOptions
{
Format = PaperFormat.A4,
Landscape = true,
MarginOptions = new MarginOptions
{
Top = "1cm",
Bottom = "1cm",
Left = "1cm",
Right = "1cm"
},
HeaderTemplate = "

Header
",
FooterTemplate = "
Page of
"
};
var pdfStream = await page.PdfStreamAsync(pdfOptions);
await browser.CloseAsync();

using (MemoryStream ms = new MemoryStream())
{
await pdfStream.CopyToAsync(ms);
return ms.ToArray();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests