My issue arises when running my code on a Linux system within a Docker container. The code, which downloads and launches Puppeteer, works flawlessly on my Windows machine. Here's the relevant snippet:
var browserFetcher = new BrowserFetcher();
var installedBrowser = await browserFetcher.DownloadAsync(BrowserTag.Latest);
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
ExecutablePath = browserFetcher.GetExecutablePath(installedBrowser.BuildId)
});
I specifically utilize GetExecutablePath(installedBrowser.BuildId) to avoid hardcoding directories. However, upon building and running the Docker container with an Alpine Linux image, I encounter the following error:
Error: An error occurred trying to start process '/app/Chrome/Linux-124.0.6335.0/chrome-linux64/chrome' with working directory '/app'. No such file or directory
Upon inspecting the container using /bin/sh, I find the necessary files exist:
I'm perplexed by this issue. If further information is required, please let me know. Thank you.
🗎 Dockerfile
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["PuppeteerProject/PuppeteerProject.csproj", "PuppeteerProject/"]
RUN dotnet restore "PuppeteerProject/PuppeteerProject.csproj"
COPY . .
WORKDIR "/src/PuppeteerProject"
RUN dotnet build "PuppeteerProject.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "PuppeteerProject.csproj" -c Release -o /app/publish
FROM mcr.microsoft.com/dotnet/aspnet:6.0
RUN apt-get update && \
apt-get install -y \
wget \
gnupg2 \
apt-transport-https \
ca-certificates \
fonts-liberation \
libappindicator3-1 \
libasound2 \
libatk-bridge2.0-0 \
libatk1.0-0 \
libcups2 \
libdbus-1-3 \
libgdk-pixbuf2.0-0 \
libnspr4 \
libnss3 \
libx11-xcb1 \
libxcomposite1 \
libxdamage1 \
libxrandr2 \
xdg-utils \
libgbm1 \
libxcb-dri3-0 \
libxss1 && \
rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=publish /app/publish .
EXPOSE 8000
CMD ["dotnet", "PuppeteerProject.dll"]
The long list of dependencies in the third build stage is to support the browser runtime.
🗎 Program.cs
using System;
using System.Threading.Tasks;
using PuppeteerSharp;
class Program
{
static async Task Main(string[] args)
{
await new BrowserFetcher().DownloadAsync();
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
Args = new string[] { "--no-sandbox", "--disable-setuid-sandbox" }
});
Console.WriteLine("Browser launched successfully.");
await browser.CloseAsync();
}
}
The example Program.cs
will run and then exit. When it exits the container will terminate.
You can, however, get a more persistent container by commenting out the CMD
line in the Dockerfile
. Then just run it manually.