【大苦戦】Ubuntuでpuppeteerを動かす
はじめに
先日、puppeteerでウェブ・スクレイピングで、puppeteerの簡単な使い方を紹介しました。この時はWindowsで作業をしており、その前提で書いてました。
しかし、いざサーバー(Ubuntu)で実行しようとしたところ、大苦戦してしまいました。しかし一応動かすところまではできたので、その方法を共有します。
結論からいうと、UbuntuでChromeを実行するためには、npm installでpuppeteerを入れるだけでは足りませんでした。他にもChromeをLinuxで動かすために、Linux用パッケージを色々インストールする必要がありました。さらに、puppeteerを起動する際にChromeのsandbox機能を無効化するようにして、はじめて動かすことができました。
特に、新しめのUbuntu(23.10以降)だと新たに導入されたセキュリティ機能の影響でそのままだと動かないことが多いようです。詳細は公式のTroubleshootingをご参照下さい。
環境
OSのバージョンとNode.jsのバージョンです。
OSはUbuntu24.04.1です。
> lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 24.04.1 LTS
Release: 24.04
Node.jsはv22.20.0です。
> node --version
v22.20.0
エラーと対応
エラーは解消しては別のエラーが出る、、、というのを複数回繰り返しました。
前提として、サーバーに資産を移し、npm installでpuppeteer等、Node.jsのパッケージのインストールまで済んだ状態です。
第一のエラー:パッケージ不足
Node.jsでpuppeteerを起動すると、まずは以下のエラーが出ました。
Error: Failed to launch the browser process!
/home/zen/.cache/puppeteer/chrome/linux-139.0.7258.66/chrome-linux64/chrome:
error while loading shared libraries: libatk-1.0.so.0: cannot open shared object file: No such file or directory
TROUBLESHOOTING: https://pptr.dev/troubleshooting
at Interface.onClose (file:///home/zen/stock/node_modules/@puppeteer/browsers/lib/esm/launch.js:314:24) at Interface.emit (node:events:531:35) at Interface.close (node:internal/readline/interface:530:10)
at Socket.onend (node:internal/readline/interface:260:10)
at Socket.emit (node:events:531:35) at endReadableNT (node:internal/streams/readable:1698:12)
at process.processTicksAndRejections (node:internal/process/task_queues:90:21)
ブラウザ起動の際に、『libatk-1.0.so.0というライブラリがないよ』と怒られています。
エラーに表示されているライブラリはこれだけですが、実はほかにもたくさんインストールが必要です。libatk-1.0.so.0だけインストールしても、別のライブラリが足りないと怒られます。
必要なライブラリの一覧は、公式のTroubleshootingのChrome doesn't launch on Linuxの、『Debian (e.g. Ubuntu) Dependencies』に記載されています。
一覧はこれです。かなり多いですが、sudo apt-get installでインストールする必要があります。
ca-certificates
fonts-liberation
libasound2
libatk-bridge2.0-0
libatk1.0-0
libc6
libcairo2
libcups2
libdbus-1-3
libexpat1
libfontconfig1
libgbm1
libgcc1
libglib2.0-0
libgtk-3-0
libnspr4
libnss3
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
lsb-release
wget
xdg-utils
この中に、仮想パッケージも一部含まれます。私の環境ではlibasound2とかがそうでした。
仮想パッケージの場合、以下のように明示的に指定するように指示されます(この場合、libasound2t64かliboss4-salsa-asound2 )。
Package libasound2 is a virtual package provided by:
libasound2t64 1.2.11-1ubuntu0.1 (= 1.2.11-1ubuntu0.1) liboss4-salsa-asound2 4.2-build2020-1ubuntu3
You should explicitly select one to install.
ちなみに、上記ではpuppeteer用途ならlibasound2t64を入れておけばほとんどの場合大丈夫なようです(ChatGPT曰く)。私もそうしましたが大丈夫でした。
「仮想パッケージ?」という方は、Debian パッケージ管理システムの基礎をご確認ください(私もよく分かってないです)。
第二のエラー:No usable sandbox!
上記の必要なパッケージをインストールし、改めてpuppeteerを実行しようとすると、今度は別のエラーが出てきました。
Error: Failed to launch the browser process:
Code: null stderr: [871251:871251:1007/221254.634266:FATAL:content/browser/zygote_host/zygote_host_impl_linux.cc:128]
No usable sandbox!
If you are running on Ubuntu 23.10+ or another Linux distro that has disabled unprivileged user namespaces with AppArmor,
see https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md.
Otherwise see https://chromium.googlesource.com/chromium/src/+/main/docs/linux/suid_sandbox_development.md
for more information on developing with the (older) SUID sandbox.
If you want to live dangerously and need an immediate workaround, you can try using --no-sandbox.
[1007/221254.640042:ERROR:third_party/crashpad/crashpad/util/file/file_io_posix.cc:145] open /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq: No such file or directory (2) [1007/221254.640227:ERROR:third_party/crashpad/crashpad/util/file/file_io_posix.cc:145] open /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq: No such file or directory (2)
Received signal 6
# 略~
No usable sandbox!と怒られています。
Ubuntuの23.10以降だと、AppArmorというセキュリティ機能が搭載されており、それがpuppeteerを妨げています。
エラーメッセージには、https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.mdを参考に対応するか、 危険を許容してサンドボックスを無効化して実行しろ、と書かれています。
前者は、ChromeをUbuntu23.10以降で動かすために、そのセキュリティ機能を一部無効化する方法が記載されています。
できればこのやり方で対応したかったのですが、私には無理でした。。
puppeteer専用の対応というより、ChromeをUbuntuで動かす場合の対応方法のため、npm i puppeteerでインストールするとchromeのインストール先が異なることが原因だとは思うのですが、、、
結局、危険を許容する方法(サンドボックス機能を無効化)を試したところ、puppeteerを動かすことができました。
サンドボックスを無効化してpuppeteerを起動するには、jsでpuppeteerを起動するときに、以下のオプションを指定すればOKです。
import puppeteer from "puppeteer";
const browser = await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
これで起動時のエラーはでなくなりましたが、はじめの2~3回はpuppeteerでページ遷移等の「待ち」を入れているところで、タイムアウトが発生しました。
もしかするとキャッシュ(?)とかの関係ではじめのうちは動作が遅いことがあるのかもしれません。以降ほとんど発生していないですが、1度だけタイムアウトが発生したため、注視したいと思います。
最後に
今回は、Ubuntuでpuppeteerを起動するときに、苦労した内容を共有させていただきました。
結局、サンドボックス無効化というやり方になってしまいましたが、、、一応、puppeteerのドキュメントでは、「信頼できるサイトでない限り推奨しない」と書かれています。
また、いまのところAppArmorが搭載されたLinuxは少ないようですが、今後は増えていく見込みのようです。
一方で、ChatGPTによると、「Ubuntuユーザーだと結局はサンドボックスを無効化して利用する場合がほとんど」とのことです。まぁ、だからと良い訳ではありませんが。
ご参考になれば幸いです。