【XQuartz】PlaywrightのためにX WindowをApple SiliconとDev Containersで動かす

Playwrightを使ってアプリを開発しているときにデバッグ起動したりUIモードで起動したりする場合、コンテナ上で起動するGUIをホストOS上に表示する必要があるため、X Window Systemが必要(Playwrightをコマンドラインのみで利用する場合いらない)。 Dev Containersを使ってる環境だと何も設定をせずにコンテナ上でGUIを起動しようとするとMissing X server or $DISPLAYのようなエラーが発生します。これを回避するにはホストOS側でXクライアントを用意してあげればいいです。

というわけで自分の場合はホストOSとしてMacを利用しているため Xquartz を使って環境を作ります。Playwrightのインストールなどのセットアップ自体はここでは触れません。

とりあえずHomebrewでXquartzをインストールします。

# Install Xquartz
$ brew install --cask xquartz

インストールしたらXQuartzを起動して、設定から以下のようにチェックを入れて、認証を不要にしつつ、コンテナからのアクセスを許可するためネットワーク・クライアントからの接続を許可します。

下記のようにコマンドラインから実行してもいい。

$ defaults write org.xquartz.X11 nolisten_tcp 0

次にDev Container側でX Window System関連の設定をします。

/tmp/.X11-unixをホスト側とコンテナ側で共有することにより、ドメインソケットを共有します。 devcontainer.jsonに以下を追加します。

"mounts": [
  {
    "type": "bind",
    "source": "/tmp/.X11-unix",
    "target": "/tmp/.X11-unix"
  }
]

実行時はホストOSのディスプレイを利用するために以下のように実行時のターミナルで環境変数を設定します。

$ export DISPLAY=host.docker.internal:0.0

もしくはこれもdevcontainer.jsonで指定してしまうこともOKです。

"containerEnv": {
  "DISPLAY": "host.docker.internal:0.0"
}

devcontainer.jsonを変更したらコンテナ自体はリビルドしてください。

あとは試しに実行してみます。以下はPythonのテストコード。

from playwright.sync_api import sync_playwright

def run():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)  # headless=True で非表示起動
        page = browser.new_page()
        page.goto("https://www.google.com")
        print(page.title())  # "Google" が出力されれば成功
        browser.close()

if __name__ == "__main__":
    run()

無事に動いた。

©Keisuke Nishitani, 2023   プライバシーポリシー