Can't run Bazel nodejs_image with Puppeteer (Error: libgobject-2.0.so.0)
Can't run Bazel nodejs_image with Puppeteer (Error: libgobject-2.0.so.0)
我正在使用 Bazel 构建 Docker 个容器:
ts_config(
name = "tsconfig",
src = "tsconfig.lib.json",
)
ts_project(
name = "lib",
srcs = ["index.ts"],
declaration = True,
tsconfig = "tsconfig",
deps = [
"@npm//@types/node",
"@npm//puppeteer",
],
)
nodejs_binary(
name = "server",
data = [
"lib",
],
entry_point = "index.ts",
)
nodejs_image(
name = "image",
binary = "server",
)
运行 nodejs_binary
工作正常。
但是 运行 nodejs_image
“图像”抛出错误:
(node:44) UnhandledPromiseRejectionWarning: Error: Failed to launch the browser process!
/app/server.runfiles/node_puppeteer/node_modules/puppeteer/.local-chromium/linux-901912/chrome-linux/chrome: error while loading shared libraries: libgobject-2.0.so.0: cannot open shared object file: No such file or directory
TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md
因此我尝试添加自定义 base
(this 一个)图像,如下所示:
nodejs_image(
name = "base_image",
base = "@nodejs_puppeteer//image",
binary = "server",
)
并在 WORKSPACE
中:
load("@io_bazel_rules_docker//container:container.bzl", "container_pull")
container_pull(
name = "nodejs_puppeteer",
digest = "sha256:22ec485fa257ec892efc2a8b69ef9a3a2a81a0f6622969ffe2d416d2a076214b",
registry = "docker.io",
repository = "drakery/node-puppeteer:latest",
)
但是 运行 更新后的 nodejs_image
“base_image”抛出此错误:
[link_node_modules.js] An error has been reported: [Error: EACCES: permission denied, symlink '/app/server.runfiles/npm/node_modules' -> 'node_modules'] {
errno: -13,
code: 'EACCES',
syscall: 'symlink',
path: '/app/server.runfiles/npm/node_modules',
dest: 'node_modules'
} Error: EACCES: permission denied, symlink '/app/server.runfiles/npm/node_modules' -> 'node_modules'
如何将缺少的依赖项添加到 nodejs_image
?
可在此处找到该问题的最小复现:https://github.com/flolu/bazel-node-puppeteer
这是使用 rules_nodejs
构建本机依赖项的一个长期存在的问题。
本机依赖项已在您的主机上构建和链接。 nodejs_image
将构建版本复制到容器镜像中,但镜像中 libgobject-2.0.so.0
等共享库的位置通常与开发机器上的位置不同。
对此没有通用的解决方案,但这里有一些可能的解决方法:
运行 npm rebuild
在你的图像的入口点。 这应该重建本机模块并根据共享库重新链接它们运行ning 容器中的位置。缺点是它会增加你的容器启动时间,而且它不一定适用于所有情况。环境特定的东西仍然可以从主机平台泄漏。
根本不要从主机复制 node_modules
。 相反,运行 npm install
或 yarn
在容器启动时。如果在容器启动时 运行ning npm rebuild
没有满足您的需要,这可能是必要的。但是,它会进一步增加启动时间。
严格控制您的开发环境,使其与您用于 nodejs_image
. 的基础映像相匹配 例如,要求所有开发工作发生在 Ubuntu 20.04,并使用与所有 nodejs_image
目标的基本图像相同的分布。或者更进一步,使用相同的基础映像将您的开发环境容器化,并在该容器中进行开发。
最后一个选项是我在实践中实际做的。我们有开发者虚拟机 运行 与我们用作所有构建映像基础的 OS 完全相同,所以事情“正常工作”。
根据 @Rohan Singh and @Noam Yizraeli 的建议,我已尝试将自定义基础映像更改为我的开发环境。
因此,我创建了一个 Docker 图像,其中 Ubuntu 作为基础,安装了 Node.js 和 Chrome:
FROM ubuntu:20.04
# Install Node.js
RUN apt-get update \
&& apt-get install -y curl
RUN curl --silent --location https://deb.nodesource.com/setup_14.x | bash -
RUN apt-get install --yes nodejs
RUN apt-get install --yes build-essential
# Install Chrome
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get install -y wget gnupg \
&& wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
&& apt-get update \
&& apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 \
--no-install-recommends \
&& rm -rf /var/lib/apt/lists/*
我把它拉进了 Bazel 是这样的:
load("@io_bazel_rules_docker//container:container.bzl", "container_pull")
container_pull(
name = "ubuntu",
digest = "sha256:a1ceb3aac586b6377821ffe6aede35c3646649ee5ac38c3566799cd04745257f",
registry = "docker.io",
repository = "drakery/node-puppeteer",
)
并像这样使用它:
nodejs_image(
name = "custom_ubuntu",
base = "@ubuntu//image",
binary = "server",
)
这是最终的工作存储库:https://github.com/flolu/bazel-node-puppeteer/tree/050376d36bccb67a93933882a459f0af3051eabd
我正在使用 Bazel 构建 Docker 个容器:
ts_config(
name = "tsconfig",
src = "tsconfig.lib.json",
)
ts_project(
name = "lib",
srcs = ["index.ts"],
declaration = True,
tsconfig = "tsconfig",
deps = [
"@npm//@types/node",
"@npm//puppeteer",
],
)
nodejs_binary(
name = "server",
data = [
"lib",
],
entry_point = "index.ts",
)
nodejs_image(
name = "image",
binary = "server",
)
运行 nodejs_binary
工作正常。
但是 运行 nodejs_image
“图像”抛出错误:
(node:44) UnhandledPromiseRejectionWarning: Error: Failed to launch the browser process!
/app/server.runfiles/node_puppeteer/node_modules/puppeteer/.local-chromium/linux-901912/chrome-linux/chrome: error while loading shared libraries: libgobject-2.0.so.0: cannot open shared object file: No such file or directory
TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md
因此我尝试添加自定义 base
(this 一个)图像,如下所示:
nodejs_image(
name = "base_image",
base = "@nodejs_puppeteer//image",
binary = "server",
)
并在 WORKSPACE
中:
load("@io_bazel_rules_docker//container:container.bzl", "container_pull")
container_pull(
name = "nodejs_puppeteer",
digest = "sha256:22ec485fa257ec892efc2a8b69ef9a3a2a81a0f6622969ffe2d416d2a076214b",
registry = "docker.io",
repository = "drakery/node-puppeteer:latest",
)
但是 运行 更新后的 nodejs_image
“base_image”抛出此错误:
[link_node_modules.js] An error has been reported: [Error: EACCES: permission denied, symlink '/app/server.runfiles/npm/node_modules' -> 'node_modules'] {
errno: -13,
code: 'EACCES',
syscall: 'symlink',
path: '/app/server.runfiles/npm/node_modules',
dest: 'node_modules'
} Error: EACCES: permission denied, symlink '/app/server.runfiles/npm/node_modules' -> 'node_modules'
如何将缺少的依赖项添加到 nodejs_image
?
可在此处找到该问题的最小复现:https://github.com/flolu/bazel-node-puppeteer
这是使用 rules_nodejs
构建本机依赖项的一个长期存在的问题。
本机依赖项已在您的主机上构建和链接。 nodejs_image
将构建版本复制到容器镜像中,但镜像中 libgobject-2.0.so.0
等共享库的位置通常与开发机器上的位置不同。
对此没有通用的解决方案,但这里有一些可能的解决方法:
运行
npm rebuild
在你的图像的入口点。 这应该重建本机模块并根据共享库重新链接它们运行ning 容器中的位置。缺点是它会增加你的容器启动时间,而且它不一定适用于所有情况。环境特定的东西仍然可以从主机平台泄漏。根本不要从主机复制
node_modules
。 相反,运行npm install
或yarn
在容器启动时。如果在容器启动时 运行ningnpm rebuild
没有满足您的需要,这可能是必要的。但是,它会进一步增加启动时间。严格控制您的开发环境,使其与您用于
nodejs_image
. 的基础映像相匹配 例如,要求所有开发工作发生在 Ubuntu 20.04,并使用与所有nodejs_image
目标的基本图像相同的分布。或者更进一步,使用相同的基础映像将您的开发环境容器化,并在该容器中进行开发。
最后一个选项是我在实践中实际做的。我们有开发者虚拟机 运行 与我们用作所有构建映像基础的 OS 完全相同,所以事情“正常工作”。
根据 @Rohan Singh and @Noam Yizraeli 的建议,我已尝试将自定义基础映像更改为我的开发环境。 因此,我创建了一个 Docker 图像,其中 Ubuntu 作为基础,安装了 Node.js 和 Chrome:
FROM ubuntu:20.04
# Install Node.js
RUN apt-get update \
&& apt-get install -y curl
RUN curl --silent --location https://deb.nodesource.com/setup_14.x | bash -
RUN apt-get install --yes nodejs
RUN apt-get install --yes build-essential
# Install Chrome
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get install -y wget gnupg \
&& wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
&& apt-get update \
&& apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 \
--no-install-recommends \
&& rm -rf /var/lib/apt/lists/*
我把它拉进了 Bazel 是这样的:
load("@io_bazel_rules_docker//container:container.bzl", "container_pull")
container_pull(
name = "ubuntu",
digest = "sha256:a1ceb3aac586b6377821ffe6aede35c3646649ee5ac38c3566799cd04745257f",
registry = "docker.io",
repository = "drakery/node-puppeteer",
)
并像这样使用它:
nodejs_image(
name = "custom_ubuntu",
base = "@ubuntu//image",
binary = "server",
)
这是最终的工作存储库:https://github.com/flolu/bazel-node-puppeteer/tree/050376d36bccb67a93933882a459f0af3051eabd