Docker上的Node.js + Puppeteer,没有可用的沙箱
我正在构建一个node.js LTS应用程序。
我遵循了伪造者文档,因此我的Dockerfile具有以下内容:
i'm building a node.js LTS application. I followed puppeteer documentation, so my Dockerfile has this content:
FROM node:12.18.0
WORKDIR /home/node/app
ADD package*.json ./
# 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.
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-unstable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf \
--no-install-recommends \
&& rm -rf /var/lib/apt/lists/*
# Install node modules
RUN npm i
# Add user so we don't need --no-sandbox.
RUN groupadd -r -f audio \
&& groupadd -r -f video \
&& usermod -a -G audio,video node \
&& mkdir -p /home/node/Downloads \
&& chown -R node:node /home/node
USER node
CMD ["google-chrome-unstable"]
应用程序构建并运行良好,但是当我尝试使用启动浏览器时,请等待puppeteer.launch();
我收到此错误:
Application builds and runs well, but as soon as i try to start browser with await puppeteer.launch();
i get this error:
pdf | Error: Failed to launch the browser process!
pdf | [0612/133635.958777:FATAL:zygote_host_impl_linux.cc(116)] No usable sandbox! Update your kernel or see https://chromium.googlesource.com/chromium/src/+/master/docs/linux/suid_sandbox_development.md for more information on developing with the SUID sandbox. If you want to live dangerously and need an immediate workaround, you can try using --no-sandbox.
pdf | #0 0x5638d5faa399 base::debug::CollectStackTrace()
pdf | #1 0x5638d5f0b2a3 base::debug::StackTrace::StackTrace()
pdf | #2 0x5638d5f1cc95 logging::LogMessage::~LogMessage()
pdf | #3 0x5638d77f940e service_manager::ZygoteHostImpl::Init()
pdf | #4 0x5638d5ad5060 content::ContentMainRunnerImpl::Initialize()
pdf | #5 0x5638d5b365e7 service_manager::Main()
pdf | #6 0x5638d5ad3631 content::ContentMain()
pdf | #7 0x5638d5b3580d headless::(anonymous namespace)::RunContentMain()
pdf | #8 0x5638d5b3550c headless::HeadlessShellMain()
pdf | #9 0x5638d35295a7 ChromeMain
pdf | #10 0x7fc01f0492e1 __libc_start_main
pdf | #11 0x5638d35293ea _start
pdf |
pdf | Received signal 6
pdf | #0 0x5638d5faa399 base::debug::CollectStackTrace()
pdf | #1 0x5638d5f0b2a3 base::debug::StackTrace::StackTrace()
pdf | #2 0x5638d5fa9f35 base::debug::(anonymous namespace)::StackDumpSignalHandler()
pdf | #3 0x7fc0255f30e0 (/lib/x86_64-linux-gnu/libpthread-2.24.so+0x110df)
pdf | #4 0x7fc01f05bfff gsignal
pdf | #5 0x7fc01f05d42a abort
pdf | #6 0x5638d5fa8e95 base::debug::BreakDebugger()
pdf | #7 0x5638d5f1d132 logging::LogMessage::~LogMessage()
pdf | #8 0x5638d77f940e service_manager::ZygoteHostImpl::Init()
pdf | #9 0x5638d5ad5060 content::ContentMainRunnerImpl::Initialize()
pdf | #10 0x5638d5b365e7 service_manager::Main()
pdf | #11 0x5638d5ad3631 content::ContentMain()
pdf | #12 0x5638d5b3580d headless::(anonymous namespace)::RunContentMain()
pdf | #13 0x5638d5b3550c headless::HeadlessShellMain()
pdf | #14 0x5638d35295a7 ChromeMain
pdf | #15 0x7fc01f0492e1 __libc_start_main
pdf | #16 0x5638d35293ea _start
pdf | r8: 0000000000000000 r9: 00007ffcd14664d0 r10: 0000000000000008 r11: 0000000000000246
pdf | r12: 00007ffcd1467788 r13: 00007ffcd1466760 r14: 00007ffcd1467790 r15: aaaaaaaaaaaaaaaa
pdf | di: 0000000000000002 si: 00007ffcd14664d0 bp: 00007ffcd1466710 bx: 0000000000000006
pdf | dx: 0000000000000000 ax: 0000000000000000 cx: 00007fc01f05bfff sp: 00007ffcd1466548
pdf | ip: 00007fc01f05bfff efl: 0000000000000246 cgf: 002b000000000033 erf: 0000000000000000
pdf | trp: 0000000000000000 msk: 0000000000000000 cr2: 0000000000000000
pdf | [end of stack trace]
pdf | Calling _exit(1). Core file will not be generated.
pdf |
pdf |
pdf | TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md
pdf |
pdf | at onClose (/home/node/app/node_modules/puppeteer/lib/launcher/BrowserRunner.js:159:20)
pdf | at Interface.<anonymous> (/home/node/app/node_modules/puppeteer/lib/launcher/BrowserRunner.js:149:65)
pdf | at Interface.emit (events.js:327:22)
pdf | at Interface.close (readline.js:416:8)
pdf | at Socket.onend (readline.js:194:10)
pdf | at Socket.emit (events.js:327:22)
pdf | at endReadableNT (_stream_readable.js:1221:12)
pdf | at processTicksAndRejections (internal/process/task_queues.js:84:21)
哦,是的,容器名称是 pdf
oh yeah, container name is pdf
我尝试按照建议的方式查看puppeteer故障排除页面,但没有找到任何解决方案。
I tried looking at puppeteer troubleshooting page as suggested, but i didn't found any solution.
有什么建议吗?
我找到了一种允许使用chrome沙箱,这要感谢此处
I found a way that allows the use of chrome sandbox, thanks to usethe4ce's answer in here
最初,我需要与puppeteer分开安装chrome,我如下编辑了Dockerfile:
Initially i needed to install chrome separately from puppeteer, i edited my Dockerfile as following:
FROM node:12.18.0
WORKDIR /home/runner/app
ADD package*.json ./
# 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.
RUN 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-unstable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst ttf-freefont \
--no-install-recommends \
&& rm -rf /var/lib/apt/lists/*
# Uncomment to skip the chromium download when installing puppeteer. If you do,
# you'll need to launch puppeteer with:
# browser.launch({executablePath: 'google-chrome-unstable'})
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
# Install node modules
RUN npm i\
# 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
&& groupadd -r runner && useradd -r -g runner -G audio,video runner \
&& mkdir -p /home/runner/Downloads \
&& chown -R runner:runner /home/runner \
&& chown -R runner:runner /home/runner/app/node_modules
USER runner
CMD ["google-chrome-unstable"]
这样做,错误从没有可用的沙箱
变为:
Failed to move to new namespace: PID namespaces supported, Network namespace supported, but failed: errno = Operation not permitted
然后我遵循usethe4ce的回答建议。
Docker默认情况下会阻止某些内核级别操作的可访问性,Seccomp选项允许解锁 chrome创建自己的沙箱所需的某些操作。
所以我添加了这个 chrome.json 文件存储到我的仓库中,然后按如下方式编辑docker-compose文件:
Then i followed usethe4ce's answer advices. Docker by default blocks accessibility to some kernel level operations, Seccomp options allow to "unlock" some of those operations that chrome needs to create his own sandbox. So i added this chrome.json file to my repo, and i edited my docker-compose file as following:
version: "3.8"
services:
<service name>:
build:
<build options>
init: true
security_opt:
- seccomp=<path to chrome.json file>
[...]
如果您不使用docker-您可以使用链接答案中建议的选项-security-opt seccomp = path / to / chrome.json
来运行容器。
If you are not using a docker-compose file you can run your container using the option --security-opt seccomp=path/to/chrome.json
as suggested in the linked answer.
最后使用以下命令启动浏览器:
Finally launch the browser using:
await puppeteer.launch({
executablePath: 'google-chrome-unstable'
});