0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vitest + Docker + ブラウザーモードでテストがハングする原因と対策

0
Posted at

先に結論だけ

Vitest + Docker + ブラウザーモードでテストがハングする場合、Dockerの共有メモリ(/dev/shm)枯渇が原因の可能性があります。対策は以下の2つを併用してください。

  1. vitest.config.tsisolate: falseを設定
  2. devcontainer.json--shm-size=2g以上を追加

はじめに

本記事では、Vitest + Docker環境でブラウザーテストがハングする原因と対策を解説します。

対象環境

  • DevContainer 0.80.2
  • Vitest 3.2.4
  • Docker 29.0.1

対象読者

コンテナー内のブラウザーテストがハングして困っている方

症状

Dockerコンテナー内で、Vitestのブラウザーモードを使い、複数のテストファイルを実行します。するとChromeプロセスがクラッシュし、Vitestがハングアップします。

通常のエラーメッセージは表示されず、Vitestはクラッシュしたプロセスからの応答を待ち続けるため、ハングアップの状態が続きます。

再現環境

Chromeをインストールしたコンテナー

Dockerイメージにgoogle-chromeパッケージをインストールして、ブラウザーモードでテストを実行する環境です。

iframeで隔離された複数テストファイル

Vitestのブラウザーモードでは、各テストファイルをiframeで隔離して実行します。テストファイル数が増えると、iframe数も増加します。

原因

Dockerのデフォルト共有メモリは64MBです。デフォルト値のままではChromeの実行には足りません。

Chrome内部のGPU Compositorが/dev/shm領域を使用します。テストファイル数が増えると、iframeごとに/dev/shm領域が消費され、メモリ不足時にChromeがクラッシュします。

Vitestはクラッシュしたプロセスからの応答を待ち続けるため、ハングアップに陥ります。

対策

対策1: isolate: false

vitest.config.tsisolate: falseを設定すると、テストファイルごとにiframeを生成せず、単一のコンテキストでテストを実行します。これにより/dev/shmのピーク消費量を削減できます。

// vitest.config.ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    browser: {
      instances: [{ browser: "chrome" }],
      isolate: false,  // Chromeインスタンスを再利用
    },
  },
});

Vitest v4ではbrowser.isolateは非推奨です。test.isolateに統合されたため、v4以降ではtest.isolate: falseを使用してください。

メリット

  • 共有メモリ消費が最小限(単一プロセス分)
  • テストファイル数増加時の拡張性が高い
  • パフォーマンスへの悪影響がない

デメリット

  • テストファイル間で状態が共有される可能性がある(テストの独立性が低下)

対策2: 共有メモリの増量

devcontainer.json--shm-size=2g以上を指定して、共有メモリを増加させます。

{
  "runArgs": ["--shm-size=2g"]
}

docker runコマンドを使用する場合は、--shm-sizeフラグを指定します。

docker run --shm-size=2g image-name

デフォルトの64MBから2GB以上に増加させることで、Chromeが使用できる共有メモリに余裕が生まれます。

メリット

  • 既存のテスト構造を変更しない
  • isolate: true(デフォルト)のまま使用可能

デメリット

  • テストが増加した時に、問題が再発する可能性がある

対策3: /dev/shmの使用を回避

Chromeの起動引数で--disable-dev-shm-usageを設定すると、Chromeは/dev/shmではなく/tmpにデータを書き込むようになります。共有メモリ枯渇の問題切り分けに有効です。

// vitest.config.ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    browser: {
      provider: 'chrome',
      launch: {
        args: ['--disable-dev-shm-usage'],
      },
    },
  },
});

メリット

  • /dev/shm枯渇の問題を回避
  • 問題が共有メモリ起因かどうかの切り分けに有効

デメリット

  • ディスクI/Oが発生するため、パフォーマンスが低下
  • 負荷が大きいテストでは/tmpへの書き込みがボトルネックとなり、テストに失敗する場合がある

余談: /dev/shm監視

Docker内で /dev/shm の使用状況を監視するには、以下のコマンドを使います。

# コンテナ内で実行
df -h /dev/shm

このコマンドで共有メモリの使用状況(合計、使用中、利用可能)を確認できます。

# 1秒ごとに監視する場合
watch -n 1 'df -h /dev/shm'

ハングアップが発生する直前に /dev/shm が満杯に近づくことを確認できます。

まとめ

Vitest + Docker + ブラウザーモード環境で共有メモリ枯渇が原因のハングを解消するには、以下の2つを併用してください。

  1. isolate: falseを設定し、Chromeインスタンスを再利用
  2. devcontainer.json--shm-size=2g以上を追加し、共有メモリを増加

Chrome起動引数(--disable-dev-shm-usage)は、問題が共有メモリ起因かどうかの切り分けに有効です。

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?