【问题标题】:Chromium inside docker image on Google Cloud RunGoogle Cloud Run 上的 docker 镜像中的 Chromium
【发布时间】:2020-12-30 19:18:41
【问题描述】:

我正在尝试在 google cloud run 上运行一个 docker 容器,该容器包含一个简单的 nodejs 应用程序和 google chromium headless 以从 HTML 源创建 PDF。 不幸的是,无论我尝试哪种解决方案,Google Cloud Run 似乎都存在问题。

我的 Docker 映像在本地和其他提供商(即 Azure)上完美运行,但 GCP 无法正常工作。

我的尝试:

基本上构建任何 docker 镜像,安装 node、npm、chromium、 然后在后台运行 chromium --headless 。 然后运行节点应用程序。 Node 应用程序只是尝试连接到 127.0.0.1:9222 => 这在 GCP 上不起作用,但在其他任何地方。

我尝试使用 docker hub 的官方节点图像 我尝试使用高山图像 我尝试使用 debian 映像 所有这些都在本地运行良好,但在谷歌云上运行却不行。

这是我对 debian 映像的最新测试:

FROM debian:latest


RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
        nodejs yarn npm chromium \
        && apt-get clean \
        && apt-get autoclean
RUN adduser --home /home/node --disabled-password --gecos "" node \
        && mkdir /home/node/app \
        && chown -R node:node /home/node/app
RUN apt-get install -y wget
RUN npm cache clean -f
RUN npm i -g n
RUN n stable
RUN node --version
RUN npm --version

USER node
WORKDIR /home/node/app
ENV CHROME_BIN=/usr/bin/chromium \
        CHROME_PATH=/usr/lib/chromium/

ARG NODE_ENV=development
ENV NODE_ENV=${NODE_ENV}


COPY --chown=node . .

RUN npm install

RUN npm run build

ENV HOST=0.0.0.0 PORT=3000

EXPOSE ${PORT}

ENTRYPOINT [ "sh", "-c", "/home/node/app/docker-inside-start.sh" ]

入口点 sh 是这样的:

#!/bin/sh
exec $CHROME_BIN --headless --use-gl=swiftshader \
        --disable-software-rasterizer --disable-dev-shm-usage --remote-debugging-port=9222 \
        --remote-debugging-address=0.0.0.0 --no-sandbox --disable-gpu \
        --no-first-run --no-crash-upload --no-pings --no-wifi &
node .

我的节点代码如下所示。没有什么花哨.. APP_CONFIG_CHROME_HOST 设置为 localhost 或 127.0.0.1 - 没有任何作用

import * as htmlPdf from 'html-pdf-chrome';
// ...
private createPdf(html: string): Promise<string> {
    return new Promise((resolve, reject) => {
      try {
        const options: htmlPdf.CreateOptions = {
          host: process.env.APP_CONFIG_CHROME_HOST,
          port: 9222, // port Chrome is listening on
        };
        htmlPdf.create(html, options)
          .then((pdf) => resolve(pdf.toBase64()))
          .catch(e => reject(e));
      } catch (err) {
        reject(err);
      }
    });
  }

最后我看到的错误/输出:

2020-09-12 15:26:02.786 MESZ[0912/132602.785920:WARNING:discardable_shared_memory_manager.cc(194)] Less than 64MB of free space in temporary directory for shared memory files: 0

2020-09-12 15:26:38.827 MESZ[0912/132638.826713:ERROR:address_tracker_linux.cc(201)] Could not bind NETLINK socket: Permission denied (13)

2020-09-12 15:26:38.828 MESZ[0912/132638.828564:ERROR:file_path_watcher_linux.cc(71)] Failed to read /proc/sys/fs/inotify/max_user_watches
...
2020-09-12 15:28:28.364 MESZ[2020-09-12T13:28:26.764Z] [ERROR] <mail.service.js> Error: socket hang up

有什么想法吗?

注意:使用高山图像时的错误是不同的。谷歌搜索指出 gcp 与那里的其他部分存在一般问题。具体来说,在 gvisor 中: https://github.com/google/gvisor/issues/1739#issuecomment-673861090 如果你想体验一下,这里有一个 docker 镜像,它与上面的镜像一样,但在 alpine 上: chrome 不会在那里运行并退出并抱怨缺少成员系统调用

FROM alpine:latest

ARG BUILD_DATE
ARG VCS_REF

LABEL org.label-schema.build-date=$BUILD_DATE \
        org.label-schema.description="Chrome running in headless mode in a tiny Alpine image" \
        org.label-schema.name="alpine-chrome" \
        org.label-schema.schema-version="1.0.0-rc1" \
        org.label-schema.usage="https://github.com/Zenika/alpine-chrome/blob/master/README.md" \
        org.label-schema.vcs-url="https://github.com/Zenika/alpine-chrome" \
        org.label-schema.vcs-ref=$VCS_REF \
        org.label-schema.vendor="Zenika" \
        org.label-schema.version="latest"

# Installs latest Chromium package.
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/main" > /etc/apk/repositories \
        && echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \
        && echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \
        && echo "http://dl-cdn.alpinelinux.org/alpine/v3.11/main" >> /etc/apk/repositories \
        && apk upgrade -U -a \
        && apk add --no-cache \
        libstdc++ \
        chromium \
        harfbuzz \
        nss \
        freetype \
        ttf-freefont \
        wqy-zenhei \
        tini make gcc g++ python git nodejs nodejs-npm yarn \
        && rm -rf /var/cache/* /var/lib/apt/lists/* /usr/share/man /tmp/*

RUN mkdir -p /home/node/app \
        && adduser -D node \
        && chown -R node:node /home/node/app

USER node
WORKDIR /home/node/app

ENV CHROME_BIN=/usr/bin/chromium-browser \
        CHROME_PATH=/usr/lib/chromium/


# set ENV to development if NOT given in command line
ARG NODE_ENV=development
ENV NODE_ENV=${NODE_ENV}

COPY --chown=node package*.json ./

RUN npm install

COPY --chown=node . .

RUN npm run build

ENV HOST=0.0.0.0 PORT=3000

EXPOSE ${PORT}
ENTRYPOINT ["/sbin/tini", "--"]
CMD [ "sh", "-c", "/home/node/app/docker-inside-start.sh" ]

【问题讨论】:

    标签: docker google-cloud-platform google-chrome-headless google-cloud-run


    【解决方案1】:

    我在 Cloud Run 中运行 chrome 以将网页转换为 PDF(并将 10 个网页转换为 SVG)。找到我的仓库here

    这是我的 Dockerfile:

    FROM node:14-slim
    
        # Add contrib packages for ms fonts
    RUN echo "deb http://http.debian.net/debian/ stretch main contrib non-free" > /etc/apt/sources.list && \
        echo "deb http://http.debian.net/debian/ stretch-updates main contrib non-free" >> /etc/apt/sources.list && \
        echo "deb http://security.debian.org/ stretch/updates main contrib non-free" >> /etc/apt/sources.list && \
        apt-get update && \
        # Adds required libs for Headless Chrome
        apt-get install -yq 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 \
        # fonts
        ttf-mscorefonts-installer fontconfig && \
        fc-cache -f
    
    # Start the app
    WORKDIR /usr/src/app
    COPY package*.json ./
    ENV NODE_ENV=production
    RUN npm install --production
    COPY . .
    CMD [ "npm", "start" ]
    

    这是我使用"puppeteer": "^3.0.4" 的 Node.js 代码的相关部分:

        if(!browser) {
            browser = await puppeteer.launch({
                args: ['--no-sandbox']
            });
        }
        if(!page) {
            page = await browser.newPage();
        }
    
        // https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#pagepdfoptions
        await page.emulateMedia('screen');
        let printParams = {
            path: inputPDFFilename,
            width,
            printBackground: true
        };
        if(height) {
            printParams.height = height;
        }
        await page.pdf(printParams);
    

    【讨论】:

    • 感谢@Sterem,这很有希望。我重新创建了相同的内容,并在本地成功执行了它。然而。部署到谷歌云运行后,我遇到了这个错误:```2020-09-14 08:28:58.260 MESZ[2020-09-14T06:28:58.060Z] [ERROR] TimeoutError : 尝试连接浏览器时 30000 毫秒后超时!只有修订版 r800071 的 Chrome 才能保证工作。```` 找到了这个:github.com/puppeteer/puppeteer/issues/4796 但我现在还没有看到解决方案。到目前为止,GCP 非常令人失望。不知道为什么我要经历这个了。
    • 只是为了跟进。我尝试使用 puppeteer 5.x。按照您的建议降级到 3.x 后。大约 30 秒后,对于不同的版本,我也得到了相同的结果:2020-09-14 09:06:47.264 MESZ[2020-09-14T07:06:45.763Z] [ERROR] &lt;mail.service.js&gt; TimeoutError: Timed out after 30000 ms while trying to connect to the browser! Only Chrome at revision r756035 is guaranteed to work. 我想我会将我们的应用程序移至 AWS 或继续在 azure 上运行它。 GCP 似乎与许多事情不兼容。 - 所有 phantomjs 版本 - chrome 无头即服务 - chrome 通过 puppeteer 直接执行
    • 来自构建日志:Step #0 - "Build": Chromium (756035) downloaded to /home/node/app/node_modules/puppeteer/.local-chromium/linux-756035
    • 我正在更新此内容并接受您的解决方案,因为我尝试了您的存储库,一切正常。不幸的是,我的具有完全相同的库和完全相同的代码的应用程序(一个 Loopback 4 项目)无法运行。所以我可能会遇到超出我范围的事情......我从所说的 api 中删除了逻辑,并为这个任务创建了一个微服务,它运行没有问题。很奇怪。话虽如此,最初的发现对我来说仍然是正确的:应用程序(带有 PDF 生成的 loopback4 在任何地方运行,但在 GCP 上。)。干杯
    • "GCP" 除了 Cloud Run 之外,还有很多其他地方可以运行容器,请查看 Kubernetes Engine 或 Compute Engine。此外,避免评论您将“将您的应用程序移至 AWS”。这与此 StackOverflow 答案无关。
    猜你喜欢
    • 2020-12-26
    • 2021-12-02
    • 2018-05-26
    • 2021-07-03
    • 1970-01-01
    • 2020-08-10
    • 2019-09-16
    • 2021-06-10
    • 2021-05-24
    相关资源
    最近更新 更多