先に結論だけ
Vitest + Docker + ブラウザーモードでテストがハングする場合、Dockerの共有メモリ(/dev/shm)枯渇が原因の可能性があります。対策は以下の2つを併用してください。
-
vitest.config.tsでisolate: falseを設定 -
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.tsでisolate: 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つを併用してください。
-
isolate: falseを設定し、Chromeインスタンスを再利用 -
devcontainer.jsonに--shm-size=2g以上を追加し、共有メモリを増加
Chrome起動引数(--disable-dev-shm-usage)は、問題が共有メモリ起因かどうかの切り分けに有効です。