c# - 启动基地失败!/app/.local-chromium/Linux-706915/chrome-linux/chrome: ... libX11.so.6
问题描述
我有一个在 ASP.NET Core 3.1 上运行的 puppeteer-sharp 实例,它在本地运行良好。对于部署,它构建在 docker 容器中并部署到 K8 开发集群。docker 容器构建良好,但应用程序在运行时失败,并Failed to launch Base! /app/.local-chromium/Linux-706915/chrome-linux/chrome: error while loading shared libraries: libX11.so.6: cannot open shared object file: No such file or directory
在尝试使用 puppeteer-sharp 时出现错误。
从以下资源中,我拼凑了以下 dockerfile。我对 docker 仍然相当缺乏经验,所以想象一下配置有问题,但我愿意接受建议!
使用的资源:
- http://www.hardkoded.com/blog/puppeteer-sharp-docker
- https://techoverflow.net/2018/06/05/how-to-fix-puppetteer-error-while-loading-shared-libraries-libx11-xcb-so-1-cannot-open-shared-object-file-没有这样的文件或目录/
- Docker NodeJS Puppeteer@2.0.0 - 如何修复无法启动 chrome!问题(headless = false 没有效果)
Dockerfile:
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
#####################
#PUPPETEER RECIPE
#####################
# Install latest chrome dev package and fonts to support major charsets (Chinese, Japanese, Arabic, Hebrew, Thai and a few others)
# Note: this installs the necessary libs to make the bundled version of Chromium that Puppeteer
# installs, work.
ARG CHROME_VERSION="81.0.4044.138-1"
RUN apt-get update && apt-get -f install && apt-get -y install apt-utils wget gnupg2
RUN apt-get -f install && apt-get -y install 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
RUN wget --no-verbose -O /tmp/chrome.deb http://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_${CHROME_VERSION}_amd64.deb \
&& apt-get update \
&& apt-get install -y /tmp/chrome.deb --no-install-recommends --allow-downgrades \
&& rm /tmp/chrome.deb
# NOTE: REMOVED THIS WHILST DEBUGGING - D
# Add user, so we don't need --no-sandbox.
# same layer as npm install to keep re-chowned files from using up several hundred MBs more space
#RUN groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser \
#&& mkdir -p /home/pptruser/Downloads \
#&& chown -R pptruser:pptruser /home/pptruser
#
## Run everything after as non-privileged user.
#
#USER pptruser
ENV PUPPETEER_EXECUTABLE_PATH "/usr/bin/google-chrome-unstable"
#####################
#END PUPPETEER RECIPE
#####################
COPY ["ProjectName.Core/ProjectName.Core.csproj", "ProjectName.Core/"]
RUN dotnet restore "ProjectName.Core/ProjectName.Core.csproj"
COPY . .
WORKDIR "/src/ProjectName.Core"
RUN dotnet build "ProjectName.Core.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "ProjectName.Core.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ProjectName.Core.dll"]
代码实现:
public static async Task<Stream> GeneratePdfFromHtml(string html, List<string> styleUrls = null)
{
await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true
});
using (var page = await browser.NewPageAsync())
{
await page.SetContentAsync(html);
if(styleUrls != null)
foreach (var url in styleUrls)
{
await page.AddStyleTagAsync(url);
}
return await page.PdfStreamAsync();
}
}
使用 Docker 的资源都针对 .NET Core 2.0,所以我不知道这是否与它有关。它在 Docker 环境之外运行良好的事实表明 .NET Core 版本不是问题,更有可能是 dockerfile 本身的一个步骤。
解决方案
好吧,事实证明这是混合的。dockerfile 需要重新排列,并且在没有沙箱的情况下效果最好。如您所见,原始代码是在中间映像上安装依赖项,而不是在 final/base 上。
出于某种原因,我无法让它在沙盒用户下正常工作,所以它被删除了。因此,实现需要更新以启用 --no-sandbox 参数。
这是其他任何努力使 puppeteer-sharp 使用 .NET Core 3.1 的人的更新代码。
dockerfile
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
#####################
#PUPPETEER RECIPE
#####################
# Install latest chrome dev package and fonts to support major charsets (Chinese, Japanese, Arabic, Hebrew, Thai and a few others)
# Note: this installs the necessary libs to make the bundled version of Chromium that Puppeteer
# installs, work.
ARG CHROME_VERSION="81.0.4044.138-1"
RUN apt-get update && apt-get -f install && apt-get -y install wget gnupg2 apt-utils
RUN wget --no-verbose -O /tmp/chrome.deb http://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_${CHROME_VERSION}_amd64.deb \
&& apt-get update \
&& apt-get install -y /tmp/chrome.deb --no-install-recommends --allow-downgrades fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf \
&& rm /tmp/chrome.deb
ENV PUPPETEER_EXECUTABLE_PATH "/usr/bin/google-chrome"
#####################
#END PUPPETEER RECIPE
#####################
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["ProjectName.Core/ProjectName.Core.csproj", "ProjectName.Core/"]
RUN dotnet restore "ProjectName.Core/ProjectName.Core.csproj"
COPY . .
WORKDIR "/src/ProjectName.Core"
RUN dotnet build "ProjectName.Core.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "ProjectName.Core.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ProjectName.Core.dll"]
执行
public static async Task<Stream> GeneratePdfFromHtml(string html, List<string> styleUrls = null)
{
await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Args = new[] { "--no-sandbox" },
Headless = true
});
using (var page = await browser.NewPageAsync())
{
await page.SetContentAsync(html);
if(styleUrls != null)
foreach (var url in styleUrls)
{
await page.AddStyleTagAsync(new AddTagOptions { Path = url });
}
return await page.PdfStreamAsync();
}
}
可能值得注意的是,puppeteer-sharp 的 docker 实现似乎也存在使用本地 url 查找样式表的问题(例如 localhost:1234/lib/bootsrap/bootsrap.min.css)。它只是永远挂起和旋转,因此AddStyleTagAsync()
改为使用文件路径。不要忘记,这是在 IHostingEnvironment.WebRootPath 下找到的,可以为您节省 google 搜索。
希望这对其他人有帮助。毫无疑问,在不远的将来,它也会再次穿越我的道路!
推荐阅读
- log4j2 - Log4j2 AsyncLogger 是否遵循插入顺序?
- java - 图像在 0 度或 180 度时停止旋转
- reactjs - 任何列上的 AG 网格中的主复选框
- swift - Swift 5.2 中的 iTunes 库框架
- imagemagick - 为什么将 CMYK 图像转换为 sRGB 以在 Web 上显示在本地工作,而不是在 prod 服务器上?
- ember.js - 我可以在两个 EmberJS 应用程序之间共享状态吗
- node.js - Nextjs 和 Express 作为中间件。如何将 'localhost:3000/newpage' 和 'localhost:3000/newpage/' 设置为相同的路由
- azure-devops - Azure DevOps Release Pipeline Managed Identity App Service 部署时出错
- function - 为什么 Rust 编译器不够聪明,无法检测同名的变量和函数?
- angular - 在 Angular 中的条件下显示选择选项