メモ: Docker コンテナー内の puppeteer からホスト上の Chrome を操作する

M1 Mac で Puppeteer を動かすのは大変というかできないみたいな話を聞いた気がする。

今のところ M1 Mac もってないので実際使えるかわからないけど、何となくこんな感じて回避できたりするかと思い、やってみたらできたのでメモ。

手順

まずはファイルをいろいろ準備する。

Dockerfile

FROM node:16

WORKDIR /app
COPY main.js proxy.js /app/

RUN npm i http-proxy puppeteer-core --save
CMD node proxy.js

main.js

const Puppeteer = require('puppeteer-core');

async function main() {
    const browser = await Puppeteer.connect({
        browserURL: 'http://127.0.0.1:9222',
    });
    const page = await browser.newPage();
    await page.goto('https://example.com/');
}

main();

proxy.js

これは main.js から host.docker.internal:9222 には直接つなげられない感じだったので雰囲気でやっている。

const httpProxy = require('http-proxy');
httpProxy
    .createProxyServer({
        target: 'http://host.docker.internal:9222',
        ws: true,
    })
    .listen(9222);

イメージをビルド

docker build -t puppeteer-with-chrome-on-host-os .

Mac 上で Chrome を起動する

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
--remote-debugging-port=9222 \
--no-first-run \
--no-default-browser-check \
--user-data-dir=$(mktemp -d -t 'chrome-remote_data_dir')

コンテナーを起動

docker run -it --rm puppeteer-with-chrome-on-host-os

何とかしてコンテナーに入る

docker exec -it [コンテナーID] bash

コンテナーで puppeteer を使ったスクリプトを実行

node main.js

うまくいけば Mac 上で起動した Chrome が以下のようになる。