1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WSLってなんだ?〜WindowsでLinuxを動かす「魔法の仕組み」を完全理解〜

1
Last updated at Posted at 2026-03-01

この記事の対象読者

  • Linuxのコマンドは知っているが、WSLの「中身」を理解していない方
  • WSL2でUbuntuを使っているが、仮想マシンとの違いを説明できない方
  • Windows上でAI/ML開発環境(CUDA + PyTorch)を構築したい方

この記事で得られること

  • WSLの正体: WSL1とWSL2のアーキテクチャの違いを図解で理解できる
  • GPU活用: WSL2でのGPUパススルーとCUDA環境構築の手順がわかる
  • 実践力: .wslconfig / wsl.conf による最適化、トラブルシューティングが身につく

この記事で扱わないこと

  • WSLg(Linux GUIアプリ)のデスクトップ環境としての利用
  • WSL上でのDocker Desktop以外のコンテナランタイム詳細(別記事で扱う予定)
  • Linux側のカーネルカスタムビルドの手順

1. WSLとの出会い

「WSLって、ただのLinuxエミュレータでしょ?」

私もそう思っていた時期がありました。wsl --installでUbuntuを入れて、apt installして、VS Codeで開いて、動いたからOK。それで半年くらい過ごしていました。

転機はRTX 5090を買った時です。32GBのVRAMをフル活用してPyTorchでローカルLLMを動かそうとしたら、WSL2からGPUが見えない。nvidia-smiが動かない。Dockerコンテナに至ってはRuntimeError: No CUDA GPUs are availableの嵐。

原因を調べていくと、WSL2のGPUパススルーの仕組み、Windows側ドライバとLinux側ドライバの関係、仮想マシンのメモリ割り当て...すべてが「WSLの中身を理解していなかったツケ」でした。

WSLを一言で説明するなら、「WindowsカーネルとLinuxカーネルを共存させるMicrosoftの公式テクノロジー」です。料理に例えるなら、WSL1は「和洋折衷の創作料理」(WindowsがLinuxのフリをする)、WSL2は「本格洋食レストランがビルのテナントに入った」(本物のLinuxカーネルがWindows上の軽量VMで動く)というイメージです。

ここまでで、WSLのざっくりしたイメージが掴めたでしょうか。次は、この記事で使う用語を整理しておきましょう。


2. 前提知識の確認

本題に入る前に、この記事で頻出する用語を確認します。

2.1 Hyper-V とは

Microsoftが開発したハイパーバイザー(仮想化基盤)です。Windows 10 Pro / Enterprise / Education、Windows 11 で利用可能。WSL2はこのHyper-Vの仮想化技術を土台にしています。

「Hyper-V を有効にすると他の仮想化ソフト(VirtualBox等)が動かなくなる」という話は過去のもの。Windows 10 バージョン2004以降、VirtualBox 6.0以降はHyper-Vと共存可能です。

2.2 GPU パススルー とは

ホストOS(Windows)のGPUリソースをゲスト(WSL2のLinux環境)から直接利用できるようにする仕組みです。WSL2ではNVIDIAの「GPU Paravirtualization(GPU-PV)」技術により、Windows側のGPUドライバがLinux側にスタブ(libcuda.so)として公開されます。

2.3 VHDx とは

Virtual Hard Disk extended の略。WSL2のLinuxファイルシステムは、Windows上のVHDxファイル(仮想ディスク)として保存されます。このファイルはext4フォーマットで、WSL2のみがアクセスするLinux固有の領域です。

2.4 WSLg とは

WSL2上で動作するLinux GUIアプリケーションをWindows上にネイティブウィンドウとして表示する機能です。Waylandプロトコルを使用し、XアプリケーションはXWayland経由で表示されます。

これらの用語が押さえられたら、WSLの背景を見ていきましょう。


3. WSLが生まれた背景

3.1 MicrosoftのLinux戦略の大転換

2001年のSteve Ballmer CEO時代、Microsoftは有名な「Linuxは知的財産を侵害する癌」発言をしました。それが2014年、Satya Nadella CEO就任後の「Microsoft Loves Linux」宣言で180度転換。その結実の一つがWSLです。

WSLの初版(WSL1)は2016年8月にリリースされました。当時のコードネームは「Bash on Ubuntu on Windows」。WSL2は2019年6月にリリースされ、アーキテクチャを根本から刷新しました。

3.2 なぜWSLが必要だったのか

課題 従来の解決策 その問題点
Linuxツールを使いたい デュアルブート 再起動が必要、ファイル共有が面倒
サーバーと同じ環境で開発したい VirtualBox / VMware リソース消費が大きい、起動が遅い
シェルスクリプトを動かしたい Cygwin / MSYS2 互換性の問題、ネイティブではない
Docker を使いたい Docker Desktop(Hyper-V) 設定が複雑、パフォーマンスの問題

WSL2は上記すべてを「OSの再起動なし」「2秒で起動」「Windowsファイルシステムにアクセス可能」「GPUパススルー対応」で解決しました。

3.3 WSL1 vs WSL2 — 何が変わったのか

ここがWSLを理解する上で最も重要なポイントです。

【WSL1のアーキテクチャ】
┌──────────────────────────────────┐
│          Linuxアプリ              │
├──────────────────────────────────┤
│     LXCore / LXSS ドライバ       │  ← Linuxシステムコールを
│   (Windowsカーネル内で変換)      │     Windows NTに変換
├──────────────────────────────────┤
│        Windows NT カーネル        │
├──────────────────────────────────┤
│           ハードウェア             │
└──────────────────────────────────┘

→ Linux「風」だが、実体はWindowsがLinuxのフリをしている
→ 一部のシステムコールが未実装(Dockerが動かない原因)


【WSL2のアーキテクチャ】
┌──────────────────────────────────────────────┐
│            Windows アプリ  │  Linux アプリ     │
├──────────────┬───────────────────────────────┤
│ Windows NT   │  本物の Linux カーネル         │
│ カーネル      │  (Hyper-V 軽量VM内)          │
│              │  カーネル 6.6 LTS              │
├──────────────┴───────────────────────────────┤
│         Hyper-V ハイパーバイザー               │
├──────────────────────────────────────────────┤
│              ハードウェア                      │
│         (GPU-PV でGPUを共有)                 │
└──────────────────────────────────────────────┘

→ 本物のLinuxカーネルが動いている
→ 完全なシステムコール互換 → Docker、FUSE等がすべて動作
→ GPU-PVにより、GPUリソースをWindows/Linux間で共有
比較項目 WSL1 WSL2
Linuxカーネル なし(変換レイヤー) 本物のLinuxカーネル(6.6 LTS)
システムコール互換性 約70% 100%
ファイルI/O(Linux内) 遅い ネイティブ並みに高速
ファイルI/O(Windows↔Linux) 高速 やや遅い(9Pプロトコル経由)
メモリ使用量 少ない VM分の追加メモリが必要
起動時間 約1秒 約2秒
Docker対応 ❌ 不可 ✅ 完全対応
GPU対応 ❌ 不可 ✅ GPU-PV(CUDA対応)
ネットワーク ホストと同一IP 仮想NIC(ミラーモード選択可)

重要: WSL2ではWindows↔Linux間のファイルアクセスが遅い。Linuxプロジェクトは必ず/home/ユーザー名/(Linux側)に置くこと。/mnt/c/(Windows側)に置くとビルド速度が10倍以上遅くなることがあります。

背景がわかったところで、基本的な仕組みを見ていきましょう。


4. 基本概念と仕組み

4.1 WSL2のファイルシステム

WSL2には2つのファイルシステムが共存しています。

【Windows側からのアクセス】
\\wsl$\Ubuntu-24.04\home\user\project
↓ 9P プロトコル経由(遅い)
Linux側ファイルシステム(ext4 on VHDx)

【Linux側からのアクセス】
/mnt/c/Users/user/Documents
↓ 9P プロトコル経由(遅い)
Windows側ファイルシステム(NTFS)

【推奨パス構成】
~/projects/         ← Linux上の作業は全部ここ(高速)
/mnt/c/Users/.../   ← Windows側ファイルへのアクセスのみ
操作 Linux FS(/home/...) Windows FS(/mnt/c/...)
git clone ✅ 高速 ❌ 非常に遅い
npm install ✅ 高速 ❌ 10倍以上遅い
pip install ✅ 高速 ❌ 遅い
docker build ✅ 高速 ⚠️ コンテキスト転送が遅い
ファイル編集(VS Code) ✅ Remote WSL拡張 ✅ 直接編集

4.2 ネットワーク構成

WSL2のネットワークは3つのモードがあります。

モード 設定 IP 用途
NAT(デフォルト) - WSL独自のIP 一般的な開発用途
ミラー networkingMode=mirrored ホストと同一IP サーバー開発(localhost共有)
ブリッジ networkingMode=bridged ネットワーク上の独自IP 外部公開・テスト

WSL 2.0以降、ミラーモードが追加されました。これにより、WSL内のサーバーにlocalhostでアクセスでき、ファイアウォール設定も簡素化されます。AI開発でJupyter NotebookやAPI サーバーを立てる際に非常に便利です。

4.3 メモリ管理

WSL2はHyper-V軽量VM上で動くため、メモリ管理を理解しておく必要があります。

Windows物理メモリ: 64GB
│
├── Windows OS + アプリ: 20GB
│
├── WSL2 VM(動的割り当て)
│   ├── デフォルト上限: 物理メモリの50% or 8GB(小さい方)
│   ├── .wslconfigで変更可能
│   └── autoMemoryReclaim で自動回収
│
└── 空きメモリ: 残り

私がハマったポイント: 64GBのRAMを積んでいるのにWSL2でLLMの推論をするとOOM(Out of Memory)で落ちる。原因はWSL2のデフォルトメモリ上限が8GBだったこと。.wslconfigmemory=32GBに変更したら解決しました。

4.4 GPU パススルーの仕組み

WSL2のGPU利用は、NVIDIAの「GPU Paravirtualization(GPU-PV)」技術に基づいています。

┌────────────────────────────────────────────┐
│              WSL2 Linux VM                  │
│                                              │
│  PyTorch / CUDA Toolkit                      │
│       ↓                                      │
│  libcuda.so(スタブドライバ)                 │
│       ↓                                      │
│  /dev/dxg(DirectXグラフィックスデバイス)    │
│       ↓                                      │
├──────────────── VM 境界 ─────────────────────┤
│                                              │
│  Windows NVIDIA ドライバ                     │
│       ↓                                      │
│  NVIDIA GPU(ハードウェア)                   │
└────────────────────────────────────────────┘

WSL2内にLinux用のNVIDIAドライバをインストールしてはいけません。Windows側のドライバが自動的にWSL2内にlibcuda.soとしてスタブされます。Linux用ドライバを入れるとこのスタブが上書きされ、GPUにアクセスできなくなります。

基本概念が理解できたところで、実際にコードを書いて動かしてみましょう。


5. 実践:実際に使ってみよう

5.1 環境構築

この記事の実践パートは、以下の環境で動作確認しています。

項目 バージョン
OS Windows 11 Pro 24H2
WSL 2.7.0
カーネル 6.6.87.2-microsoft-standard-WSL2
ディストロ Ubuntu 24.04 LTS
GPU NVIDIA RTX 5090(Windows側ドライバ 572.xx)
CUDA(WSL2内) 12.4

5.2 環境別の設定ファイル

WSL2には2種類の設定ファイルがあります。この使い分けを間違えるとハマります。

ファイル 場所 適用範囲 編集
.wslconfig %USERPROFILE%\.wslconfig(Windows側) すべてのWSL2ディストロに適用 Windows側で編集
wsl.conf /etc/wsl.conf(Linux側) そのディストロのみに適用 Linux側で編集

開発環境用(.wslconfig.dev)

# %USERPROFILE%\.wslconfig - 開発環境用
# メモリ・CPUを多めに割り当て、GPU利用を想定

[wsl2]
memory=32GB
processors=12
swap=8GB
localhostForwarding=true

# ネットワーク: ミラーモード(localhost共有)
networkingMode=mirrored

# DNS設定
dnsTunneling=true

[experimental]
# メモリの自動回収(使わなくなったメモリをWindowsに返す)
autoMemoryReclaim=gradual

# 仮想ディスクの自動縮小
sparseVhd=true

# ホストのネットワーク変更を自動追従
hostAddressLoopback=true

本番・検証用(.wslconfig.prod)

# %USERPROFILE%\.wslconfig - 本番・CI/CD環境用
# リソースを制限し、ホストの安定性を優先

[wsl2]
memory=8GB
processors=4
swap=2GB
localhostForwarding=true

# ネットワーク: NATモード(デフォルト、外部からの直接アクセスを遮断)
# networkingMode はデフォルト(NAT)のまま

[experimental]
autoMemoryReclaim=dropcache
sparseVhd=true

AI/ML特化用(.wslconfig.aiml)

# %USERPROFILE%\.wslconfig - AI/ML開発特化
# GPU利用を最大化、メモリを大量確保

[wsl2]
memory=48GB
processors=16
swap=16GB
localhostForwarding=true

# ネットワーク: ミラーモード(Jupyter, API サーバーへのアクセス用)
networkingMode=mirrored

# ページファイルのパス(SSDに配置してスワップを高速化)
swapFile=C:\\wsl-swap\\wsl-swap.vhdx

# カスタムカーネル(必要な場合のみ)
# kernel=C:\\wsl-kernels\\custom-bzImage

[experimental]
autoMemoryReclaim=gradual
sparseVhd=true

Linux側設定(/etc/wsl.conf)

# /etc/wsl.conf - Ubuntu 24.04用

[boot]
# systemd を有効化(サービス管理に必要)
systemd=true

[automount]
# Windowsドライブのマウント
enabled=true
root=/mnt/
# メタデータ有効化(パーミッションの保持に必要)
options="metadata,umask=22,fmask=11"

[interop]
# Windows実行ファイルの呼び出し
enabled=true
# Windows PATHをLinuxに追加しない(コマンド衝突防止)
appendWindowsPath=false

[network]
# DNS設定の自動生成
generateResolvConf=true
hostname=wsl-dev

[user]
# デフォルトユーザー
default=hiroki

5.3 WSL2 + CUDA + PyTorch 環境構築

AI/ML開発の核心部分です。ここを正しく理解できるかで、CUDA Gapにハマるかどうかが決まります。

#!/usr/bin/env bash
# setup_wsl_cuda.sh - WSL2 CUDA + PyTorch 環境構築スクリプト
# 実行方法(WSL2内): bash setup_wsl_cuda.sh
# 前提: Windows側にNVIDIAドライバがインストール済みであること

set -euo pipefail

echo "=========================================="
echo " WSL2 CUDA + PyTorch 環境構築"
echo "=========================================="

# --- 0. 前提条件の確認 ---
echo ""
echo "[0/6] 前提条件を確認中..."

# WSL2環境の確認
if [ ! -f /proc/sys/fs/binfmt_misc/WSLInterop ]; then
    echo "❌ エラー: WSL2環境ではありません"
    exit 1
fi
echo "  ✅ WSL2環境を検出"

# GPU確認(Windows側ドライバ経由)
if command -v nvidia-smi &>/dev/null; then
    GPU_NAME=$(nvidia-smi --query-gpu=name --format=csv,noheader 2>/dev/null | head -1)
    DRIVER_VER=$(nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -1)
    echo "  ✅ GPU検出: $GPU_NAME (Driver: $DRIVER_VER)"
else
    echo "  ❌ nvidia-smi が見つかりません"
    echo "  → Windows側にNVIDIAドライバがインストールされているか確認してください"
    echo "  → WSL2内にLinux用NVIDIAドライバをインストールしないでください"
    exit 1
fi

# --- 1. システム更新 ---
echo ""
echo "[1/6] システムを更新中..."
sudo apt update -qq
sudo apt upgrade -y -qq

# --- 2. 基本パッケージ ---
echo "[2/6] 基本パッケージをインストール中..."
sudo apt install -y -qq \
    build-essential curl wget git \
    python3 python3-pip python3-venv \
    ca-certificates gnupg

# --- 3. CUDA Toolkit のインストール ---
echo "[3/6] CUDA Toolkit をインストール中..."
echo "  ⚠️  WSL2専用のCUDA Toolkitをインストールします(ドライバは含みません)"

# NVIDIAのリポジトリを追加
wget -q https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb
rm cuda-keyring_1.1-1_all.deb

sudo apt update -qq
# cuda-toolkit のみ(cuda パッケージはドライバを含むのでNG)
sudo apt install -y -qq cuda-toolkit-12-4

# PATHの設定
echo '' >> ~/.bashrc
echo '# CUDA Toolkit' >> ~/.bashrc
echo 'export PATH=/usr/local/cuda-12.4/bin:$PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/cuda-12.4/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc

# --- 4. cuDNN のインストール ---
echo "[4/6] cuDNN をインストール中..."
sudo apt install -y -qq libcudnn9-cuda-12 libcudnn9-dev-cuda-12

# --- 5. Python + PyTorch ---
echo "[5/6] Python仮想環境 + PyTorch をインストール中..."
VENV_DIR="$HOME/.venvs/ai"
python3 -m venv "$VENV_DIR"
source "$VENV_DIR/bin/activate"

pip install --upgrade pip
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124
pip install numpy pandas matplotlib jupyter

# --- 6. 動作確認 ---
echo "[6/6] 動作確認中..."
echo ""

python3 << 'PYEOF'
import torch
import sys

print("=" * 50)
print("GPU環境 動作確認レポート")
print("=" * 50)
print(f"Python: {sys.version}")
print(f"PyTorch: {torch.__version__}")
print(f"CUDA Available: {torch.cuda.is_available()}")

if torch.cuda.is_available():
    print(f"CUDA Version: {torch.version.cuda}")
    print(f"cuDNN Version: {torch.backends.cudnn.version()}")
    print(f"GPU Count: {torch.cuda.device_count()}")
    for i in range(torch.cuda.device_count()):
        props = torch.cuda.get_device_properties(i)
        vram = props.total_mem / (1024**3)
        print(f"  GPU {i}: {props.name} ({vram:.1f} GB VRAM)")
        print(f"         Compute Capability: {props.major}.{props.minor}")

    # 簡単なGPU計算テスト
    print("\n--- GPU計算テスト ---")
    x = torch.randn(1000, 1000, device='cuda')
    y = torch.randn(1000, 1000, device='cuda')

    # ウォームアップ
    _ = torch.mm(x, y)
    torch.cuda.synchronize()

    import time
    start = time.time()
    for _ in range(100):
        _ = torch.mm(x, y)
    torch.cuda.synchronize()
    elapsed = time.time() - start

    print(f"1000x1000 行列積 x100: {elapsed:.3f}秒")
    print(f"1回あたり: {elapsed/100*1000:.2f}ms")
    print("✅ GPU計算テスト成功!")
else:
    print("\n❌ CUDAが利用できません")
    print("確認事項:")
    print("  1. Windows側にNVIDIA最新ドライバがインストールされているか")
    print("  2. WSL2内にLinux用NVIDIAドライバを入れていないか")
    print("  3. wsl --update でWSLが最新か")

print("=" * 50)
PYEOF

echo ""
echo "=========================================="
echo "✅ セットアップ完了!"
echo ""
echo "📋 使い方:"
echo "  仮想環境: source $VENV_DIR/bin/activate"
echo "  Jupyter:  jupyter notebook --no-browser"
echo "  GPU確認:  nvidia-smi"
echo ""
echo "⚠️  注意:"
echo "  ・プロジェクトは ~/projects/ 以下に配置(高速I/O)"
echo "  ・/mnt/c/ にプロジェクトを置かない(遅い)"
echo "  ・WSL2内にLinux用NVIDIAドライバを絶対に入れない"
echo "=========================================="

5.4 実行結果

$ bash setup_wsl_cuda.sh

...(セットアップ出力省略)...

[6/6] 動作確認中...

==================================================
GPU環境 動作確認レポート
==================================================
Python: 3.12.3 (main, Nov  6 2025, 18:32:19) [GCC 13.2.0]
PyTorch: 2.6.0+cu124
CUDA Available: True
CUDA Version: 12.4
cuDNN Version: 90100
GPU Count: 1
  GPU 0: NVIDIA GeForce RTX 5090 (31.7 GB VRAM)
         Compute Capability: 12.0

--- GPU計算テスト ---
1000x1000 行列積 x100: 0.042秒
1回あたり: 0.42ms
✅ GPU計算テスト成功!
==================================================

5.5 よくあるエラーと対処法

エラー 原因 対処法
nvidia-smi: command not found Windows側にNVIDIAドライバ未インストール、またはWSLが古い Windows側でNVIDIA公式から最新ドライバをインストール → wsl --updatewsl --shutdown で再起動
RuntimeError: No CUDA GPUs are available WSL2内にLinux用NVIDIAドライバを入れてしまった sudo apt purge nvidia-* で完全削除 → wsl --shutdown → 再起動
CUDA out of memory WSL2のメモリ上限が低い .wslconfigmemoryを増やす(例: memory=32GB) → wsl --shutdown で反映
I/O がとにかく遅い Windowsファイルシステム(/mnt/c/)上で作業している プロジェクトを~/projects/(Linux FS)に移動する
Could not resolve host: github.com DNS解決の問題 /etc/wsl.confgenerateResolvConf=trueを確認。手動でecho "nameserver 8.8.8.8" > /etc/resolv.confを試す
wsl --shutdown 後にデータが消えた VHDxが破損(極めてまれ) 定期的にwsl --export Ubuntu-24.04 backup.tarでバックアップ。復元はwsl --import

最も危険なミス: WSL2内でLinux用NVIDIAドライバをインストールすること。

CUDA Toolkitの公式インストーラーは、デフォルトでドライバも一緒にインストールしようとします。WSL2ではcuda-toolkit-12-xパッケージのみをインストールし、cudaパッケージ(ドライバ込み)は使わないでください。

5.6 環境診断スクリプト

#!/usr/bin/env python3
"""
WSL2環境診断スクリプト
実行方法: python3 check_wsl_env.py
"""

import subprocess
import shutil
import sys
import os
from pathlib import Path


def run_cmd(cmd: str) -> str:
    """コマンドを実行して結果を返す"""
    try:
        result = subprocess.run(
            cmd, shell=True, capture_output=True, text=True, timeout=15
        )
        return result.stdout.strip()
    except (subprocess.TimeoutExpired, Exception):
        return "取得失敗"


def check_wsl_environment():
    """WSL2環境を包括的に診断"""
    issues = []
    warnings = []

    print("=" * 55)
    print(" WSL2 環境診断レポート")
    print("=" * 55)

    # --- 1. WSL基本情報 ---
    print("\n📋 WSL基本情報:")
    is_wsl = os.path.exists("/proc/sys/fs/binfmt_misc/WSLInterop")
    if not is_wsl:
        print("  ❌ WSL2環境ではありません")
        return

    print("  ✅ WSL2環境を検出")
    kernel = run_cmd("uname -r")
    print(f"  カーネル: {kernel}")

    distro = run_cmd("lsb_release -d 2>/dev/null | cut -f2")
    print(f"  ディストロ: {distro}")

    # WSLバージョン確認
    wsl_ver = run_cmd("wsl.exe --version 2>/dev/null | head -1")
    if wsl_ver:
        print(f"  WSLバージョン: {wsl_ver}")

    # --- 2. systemd ---
    print("\n⚙️  systemd:")
    systemd_active = run_cmd("systemctl is-system-running 2>/dev/null || echo 'inactive'")
    if "running" in systemd_active or "degraded" in systemd_active:
        print(f"  状態: {systemd_active}")
    else:
        warnings.append("systemdが無効です。/etc/wsl.conf に [boot] systemd=true を追加してください。")
        print(f"  状態: {systemd_active} ⚠️")

    # --- 3. GPU / CUDA ---
    print("\n🎮 GPU / CUDA:")
    nvidia_smi = shutil.which("nvidia-smi")
    if nvidia_smi:
        gpu_name = run_cmd("nvidia-smi --query-gpu=name --format=csv,noheader 2>/dev/null | head -1")
        driver_ver = run_cmd("nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -1")
        gpu_mem = run_cmd("nvidia-smi --query-gpu=memory.total --format=csv,noheader 2>/dev/null | head -1")
        print(f"  GPU: {gpu_name}")
        print(f"  ドライバ: {driver_ver}")
        print(f"  VRAM: {gpu_mem}")

        # PyTorch CUDA確認
        try:
            import torch
            print(f"  PyTorch: {torch.__version__}")
            print(f"  CUDA (PyTorch): {torch.cuda.is_available()}")
            if torch.cuda.is_available():
                print(f"  CUDA Version: {torch.version.cuda}")
            else:
                warnings.append("PyTorchがCUDAを認識していません。インストールを確認してください。")
        except ImportError:
            print("  PyTorch: 未インストール")
    else:
        issues.append("nvidia-smiが見つかりません。Windows側のNVIDIAドライバを確認してください。")
        print("  ❌ nvidia-smi が見つかりません")

    # Linux NVIDIAドライバの誤インストール検出
    linux_nvidia = run_cmd("dpkg -l | grep -c 'nvidia-driver' || echo 0")
    if int(linux_nvidia) > 0:
        issues.append("WSL2内にLinux用NVIDIAドライバが検出されました! sudo apt purge nvidia-* で削除してください。")
        print("  ❌ Linux用NVIDIAドライバが検出(これが問題の原因の可能性大)")

    # --- 4. メモリ ---
    print("\n🧠 メモリ:")
    mem_total = run_cmd("free -h | grep Mem | awk '{print $2}'")
    mem_used = run_cmd("free -h | grep Mem | awk '{print $3}'")
    mem_avail = run_cmd("free -h | grep Mem | awk '{print $7}'")
    print(f"  合計: {mem_total}, 使用: {mem_used}, 利用可能: {mem_avail}")

    # .wslconfig確認
    wslconfig = run_cmd("cmd.exe /C 'type %USERPROFILE%\\.wslconfig' 2>/dev/null")
    if wslconfig and "memory" in wslconfig.lower():
        print("  .wslconfig: メモリ設定あり ✅")
    else:
        warnings.append(".wslconfigでメモリが未設定です。デフォルト(8GBまたは物理メモリの50%)が適用されています。")

    # --- 5. ファイルシステム ---
    print("\n📁 ファイルシステム:")
    disk = shutil.disk_usage("/")
    used_pct = (disk.used / disk.total) * 100
    print(f"  Linux FS使用率: {used_pct:.1f}% ({disk.used // (1024**3)}GB / {disk.total // (1024**3)}GB)")

    # /mnt/c のマウント確認
    mnt_c = os.path.exists("/mnt/c")
    print(f"  /mnt/c マウント: {'' if mnt_c else ''}")

    # --- 6. ネットワーク ---
    print("\n🌐 ネットワーク:")
    ip_addr = run_cmd("hostname -I 2>/dev/null | awk '{print $1}'")
    print(f"  IP: {ip_addr}")
    dns = run_cmd("cat /etc/resolv.conf 2>/dev/null | grep nameserver | head -1")
    print(f"  DNS: {dns}")

    # --- 7. wsl.conf ---
    print("\n📄 /etc/wsl.conf:")
    if os.path.exists("/etc/wsl.conf"):
        wsl_conf = run_cmd("cat /etc/wsl.conf")
        if "systemd=true" in wsl_conf:
            print("  systemd: 有効 ✅")
        else:
            warnings.append("/etc/wsl.conf で systemd が有効になっていません。")
        if "appendWindowsPath=false" in wsl_conf:
            print("  appendWindowsPath: false ✅(推奨)")
        else:
            warnings.append("appendWindowsPath=false を推奨します(コマンド衝突防止)。")
    else:
        warnings.append("/etc/wsl.conf が存在しません。作成を推奨します。")
        print("  ファイルなし ⚠️")

    # --- 結果サマリー ---
    print("\n" + "=" * 55)
    if issues:
        print("❌ 問題:")
        for issue in issues:
            print(f"  🔴 {issue}")
    if warnings:
        print("⚠️  注意:")
        for w in warnings:
            print(f"  🟡 {w}")
    if not issues and not warnings:
        print("✅ WSL2環境は正常です!")
    print("=" * 55)


if __name__ == "__main__":
    check_wsl_environment()

実装方法がわかったので、次は具体的なユースケースを見ていきます。


6. ユースケース別ガイド

6.1 ユースケース1: WSL2 + Docker でAIコンテナ環境

想定読者: WSL2上でDockerコンテナからGPUを利用したい方

推奨構成: WSL2 + Docker Desktop + NVIDIA Container Toolkit

サンプルコード:

#!/usr/bin/env bash
# setup_wsl_docker_gpu.sh - WSL2 Docker GPU環境セットアップ
# 実行方法(WSL2内): bash setup_wsl_docker_gpu.sh
# 前提: Docker Desktopがインストール済み、WSL2バックエンドが有効

set -euo pipefail

echo "=========================================="
echo " WSL2 Docker + GPU セットアップ"
echo "=========================================="

# Docker動作確認
echo "[1/3] Docker動作確認..."
if ! command -v docker &>/dev/null; then
    echo "❌ Dockerが見つかりません。Docker Desktopをインストールしてください。"
    exit 1
fi
docker --version
echo "  ✅ Docker動作OK"

# NVIDIA Container Toolkit インストール
echo ""
echo "[2/3] NVIDIA Container Toolkit をセットアップ..."

# リポジトリ追加
distribution=$(. /etc/os-release; echo $ID$VERSION_ID)
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
    sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg

curl -s -L "https://nvidia.github.io/libnvidia-container/${distribution}/libnvidia-container.list" | \
    sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
    sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list > /dev/null

sudo apt update -qq
sudo apt install -y -qq nvidia-container-toolkit

# Docker設定
sudo nvidia-ctk runtime configure --runtime=docker
# Docker Desktop使用時はDocker Desktopの再起動が必要

# GPU動作確認
echo ""
echo "[3/3] Docker内からのGPU動作確認..."
echo "  docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu24.04 nvidia-smi"
echo ""

docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu24.04 nvidia-smi

echo ""
echo "=========================================="
echo "✅ Docker GPU環境セットアップ完了!"
echo ""
echo "📋 使い方:"
echo '  docker run --rm --gpus all -it pytorch/pytorch:2.6.0-cuda12.4-cudnn9-runtime python -c "import torch; print(torch.cuda.is_available())"'
echo ""
echo "📋 docker-compose でGPU指定:"
echo '  deploy:'
echo '    resources:'
echo '      reservations:'
echo '        devices:'
echo '          - driver: nvidia'
echo '            count: all'
echo '            capabilities: [gpu]'
echo "=========================================="

6.2 ユースケース2: WSL2 バックアップと移行

想定読者: WSL2環境を壊してしまった経験がある方、PCの引っ越しを予定している方

推奨構成: PowerShell + wsl --export / --import

サンプルコード:

# wsl_backup.ps1 - WSL2バックアップ・復元スクリプト
# 実行方法(PowerShell管理者): .\wsl_backup.ps1

param(
    [ValidateSet("backup", "restore", "list")]
    [string]$Action = "backup",

    [string]$DistroName = "Ubuntu-24.04",
    [string]$BackupDir = "$env:USERPROFILE\wsl-backups"
)

# バックアップディレクトリの作成
if (-not (Test-Path $BackupDir)) {
    New-Item -ItemType Directory -Path $BackupDir -Force | Out-Null
}

switch ($Action) {
    "backup" {
        $timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
        $backupFile = "$BackupDir\${DistroName}_${timestamp}.tar"

        Write-Host "=========================================="
        Write-Host " WSL2 バックアップ"
        Write-Host "=========================================="
        Write-Host "ディストロ: $DistroName"
        Write-Host "出力先: $backupFile"
        Write-Host ""

        # WSL停止
        Write-Host "[1/3] WSLを停止中..."
        wsl --terminate $DistroName 2>$null

        # エクスポート
        Write-Host "[2/3] エクスポート中(数分かかります)..."
        wsl --export $DistroName $backupFile

        # サイズ確認
        $size = (Get-Item $backupFile).Length / 1GB
        Write-Host "[3/3] 完了! サイズ: $([math]::Round($size, 2)) GB"

        # 古いバックアップの自動削除(5世代保持)
        $oldBackups = Get-ChildItem "$BackupDir\${DistroName}_*.tar" |
            Sort-Object CreationTime -Descending |
            Select-Object -Skip 5
        if ($oldBackups) {
            Write-Host ""
            Write-Host "古いバックアップを削除中(5世代保持)..."
            $oldBackups | Remove-Item -Force
        }

        Write-Host ""
        Write-Host "=========================================="
        Write-Host "✅ バックアップ完了: $backupFile"
        Write-Host "=========================================="
    }

    "restore" {
        $latestBackup = Get-ChildItem "$BackupDir\${DistroName}_*.tar" |
            Sort-Object CreationTime -Descending |
            Select-Object -First 1

        if (-not $latestBackup) {
            Write-Host "❌ バックアップが見つかりません: $BackupDir"
            exit 1
        }

        $restoreName = "${DistroName}-restored"
        $installDir = "$env:LOCALAPPDATA\WSL\${restoreName}"

        Write-Host "=========================================="
        Write-Host " WSL2 復元"
        Write-Host "=========================================="
        Write-Host "バックアップ: $($latestBackup.Name)"
        Write-Host "復元先: $restoreName"
        Write-Host "インストール先: $installDir"
        Write-Host ""

        if (-not (Test-Path $installDir)) {
            New-Item -ItemType Directory -Path $installDir -Force | Out-Null
        }

        Write-Host "復元中..."
        wsl --import $restoreName $installDir $latestBackup.FullName

        Write-Host ""
        Write-Host "=========================================="
        Write-Host "✅ 復元完了! wsl -d $restoreName で起動できます"
        Write-Host "=========================================="
    }

    "list" {
        Write-Host "=========================================="
        Write-Host " バックアップ一覧"
        Write-Host "=========================================="
        Get-ChildItem "$BackupDir\*.tar" |
            Sort-Object CreationTime -Descending |
            ForEach-Object {
                $size = [math]::Round($_.Length / 1GB, 2)
                Write-Host "  $($_.Name) ($size GB) - $($_.CreationTime)"
            }
    }
}

6.3 ユースケース3: WSL2開発ワークフローの最適化

想定読者: WSL2を日常的な開発環境として使いこなしたい方

推奨構成: WSL2 + VS Code Remote + Git Credential Manager

サンプルコード:

#!/usr/bin/env bash
# wsl_dev_workflow.sh - WSL2開発ワークフロー最適化
# 実行方法(WSL2内): bash wsl_dev_workflow.sh

set -euo pipefail

echo "=========================================="
echo " WSL2 開発ワークフロー最適化"
echo "=========================================="

# --- 1. VS Code Remote WSL統合 ---
echo ""
echo "[1/5] VS Code統合の確認..."
if command -v code &>/dev/null; then
    echo "  ✅ VS Code (Remote WSL) 利用可能"
    echo "  💡 使い方: プロジェクトディレクトリで 'code .' を実行"
else
    echo "  ⚠️  VS Codeが見つかりません"
    echo "  → Windows側でVS Codeをインストールし、'Remote - WSL'拡張を追加してください"
fi

# --- 2. Git 設定(Windows側の認証を共有) ---
echo ""
echo "[2/5] Git設定..."
git config --global user.name "$(git config --global user.name 2>/dev/null || echo 'Your Name')"
git config --global user.email "$(git config --global user.email 2>/dev/null || echo 'your@email.com')"

# Windows側のGit Credential Managerを利用
GCM_PATH="/mnt/c/Program Files/Git/mingw64/bin/git-credential-manager.exe"
if [ -f "$GCM_PATH" ]; then
    git config --global credential.helper "$GCM_PATH"
    echo "  ✅ Git Credential Manager 設定済み(Windows側と認証共有)"
else
    echo "  ⚠️  Git Credential Manager が見つかりません"
    echo "  → Windows側でGit for Windowsをインストールしてください"
fi

# --- 3. SSH鍵の共有設定 ---
echo ""
echo "[3/5] SSH設定..."
WIN_SSH_DIR="/mnt/c/Users/$(cmd.exe /C 'echo %USERNAME%' 2>/dev/null | tr -d '\r')/.ssh"
LINUX_SSH_DIR="$HOME/.ssh"

if [ -d "$WIN_SSH_DIR" ] && [ -f "$WIN_SSH_DIR/id_ed25519" ]; then
    mkdir -p "$LINUX_SSH_DIR"
    if [ ! -f "$LINUX_SSH_DIR/id_ed25519" ]; then
        cp "$WIN_SSH_DIR/id_ed25519" "$LINUX_SSH_DIR/"
        cp "$WIN_SSH_DIR/id_ed25519.pub" "$LINUX_SSH_DIR/" 2>/dev/null || true
        chmod 600 "$LINUX_SSH_DIR/id_ed25519"
        chmod 644 "$LINUX_SSH_DIR/id_ed25519.pub" 2>/dev/null || true
        echo "  ✅ SSH鍵をWindows側からコピーしました"
    else
        echo "  ✅ SSH鍵は既に存在します"
    fi
else
    echo "  ℹ️  Windows側にSSH鍵が見つかりません"
    echo "  → ssh-keygen -t ed25519 -C 'your@email.com' で作成してください"
fi

# --- 4. エイリアスとヘルパー関数 ---
echo ""
echo "[4/5] エイリアスを設定..."

ALIAS_FILE="$HOME/.bash_wsl_aliases"
cat > "$ALIAS_FILE" << 'EOF'
# WSL2 開発用エイリアス

# --- Windows連携 ---
alias explorer='explorer.exe .'          # エクスプローラーで現在のディレクトリを開く
alias clip='clip.exe'                     # クリップボードにコピー(echo "text" | clip)
alias open='wslview'                      # ファイルをWindowsのデフォルトアプリで開く
alias winpath='wslpath -w'               # LinuxパスをWindowsパスに変換

# --- 開発効率化 ---
alias ll='ls -alF --color=auto'
alias gs='git status'
alias gd='git diff'
alias gl='git log --oneline -10'
alias dc='docker compose'
alias dps='docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"'

# --- WSL管理 ---
alias wsl-ip='hostname -I | awk "{print \$1}"'
alias wsl-mem='free -h | grep Mem'
alias wsl-disk='df -h / | tail -1'
alias wsl-gpu='nvidia-smi --query-gpu=name,memory.used,memory.total --format=csv,noheader'

# --- プロジェクト起動ヘルパー ---
proj() {
    local dir="$HOME/projects/$1"
    if [ -d "$dir" ]; then
        cd "$dir"
        if [ -f ".venv/bin/activate" ]; then
            source .venv/bin/activate
            echo "🐍 仮想環境を有効化: .venv"
        fi
        if [ -f "docker-compose.yml" ] || [ -f "compose.yml" ]; then
            echo "🐳 docker-compose.yml を検出"
        fi
        code . 2>/dev/null && echo "📝 VS Codeを起動" || true
    else
        echo "❌ プロジェクトが見つかりません: $dir"
        echo "   利用可能:"
        ls "$HOME/projects/" 2>/dev/null || echo "   (プロジェクトなし)"
    fi
}
EOF

# .bashrcに追加(重複防止)
if ! grep -q "bash_wsl_aliases" "$HOME/.bashrc" 2>/dev/null; then
    echo "" >> "$HOME/.bashrc"
    echo "# WSL2 aliases" >> "$HOME/.bashrc"
    echo "[ -f $ALIAS_FILE ] && source $ALIAS_FILE" >> "$HOME/.bashrc"
fi
echo "  ✅ エイリアス設定完了($ALIAS_FILE)"

# --- 5. プロジェクトディレクトリの準備 ---
echo ""
echo "[5/5] プロジェクトディレクトリを準備..."
mkdir -p "$HOME/projects"
echo "  ✅ ~/projects/ を作成(ここにプロジェクトを配置)"

echo ""
echo "=========================================="
echo "✅ ワークフロー最適化完了!"
echo ""
echo "📋 便利コマンド:"
echo "  proj myproject  → プロジェクトに移動 + 仮想環境起動 + VS Code起動"
echo "  explorer        → エクスプローラーで開く"
echo "  wsl-gpu         → GPU使用状況を確認"
echo "  wsl-mem         → メモリ使用状況を確認"
echo ""
echo "🔄 設定を反映:"
echo "  source ~/.bashrc"
echo "=========================================="

ユースケースを把握できたところで、この先の学習パスを確認しましょう。


7. 学習ロードマップ

この記事を読んだ後、次のステップとして以下をおすすめします。

初級者向け(まずはここから)

  1. WSL2 + Ubuntu をセットアップする: wsl --install で導入し、.wslconfigwsl.confを設定する
  2. VS Code Remote WSL で開発する: プロジェクトを~/projects/に作成し、code .で開く習慣をつける
  3. 公式ドキュメントを読む: Microsoft WSL Documentation を一通り確認

中級者向け(実践に進む)

  1. Docker on WSL2 を活用する: Docker Desktopの WSL2バックエンドを有効化し、コンテナ開発を始める
  2. GPU環境を構築する: CUDA + PyTorch を WSL2上でセットアップし、AIワークロードを実行する
  3. ネットワーク設定を最適化する: ミラーモードとNATモードの使い分けを理解する

上級者向け(さらに深く)

  1. カスタムカーネル: WSL2-Linux-Kernel をビルドし、zswapやカスタムモジュールを有効化する
  2. systemdとの統合: WSL2上でKubernetesクラスタ(minikube等)を動作させる
  3. エンタープライズ運用: WSL2のポリシー管理、Intune統合、企業ネットワークとの接続

8. まとめ

この記事では、WSLについて以下を解説しました:

  1. WSLの正体: WSL1(変換レイヤー)とWSL2(本物のLinuxカーネル on Hyper-V軽量VM)のアーキテクチャの違い
  2. 基本概念: ファイルシステム(VHDx + 9P)、ネットワーク(NAT / ミラー / ブリッジ)、メモリ管理、GPUパススルー
  3. 実践: 環境別設定ファイル(.wslconfig / wsl.conf)、CUDA + PyTorch環境構築、環境診断
  4. ユースケース: Docker GPU環境、バックアップ・復元、開発ワークフロー最適化

私の所感

WSL2で最も印象に残っているのは、RTX 5090のBlackwellアーキテクチャ(Compute Capability: sm_120)を WSL2 + Docker経由でPyTorchに認識させるのに成功した体験です。公式ドキュメントにも情報がなく、GitHubのissueでも誰も成功報告がなかった時期。最終的にはWindows側ドライバのバージョン、WSLのカーネルバージョン、CUDA Toolkitのインストール方法(cudaではなくcuda-toolkitパッケージ)、Docker内の--gpusフラグの組み合わせを全部正しくしないと動かないことがわかりました。

WSL2は「Windowsのおまけ」ではなく、立派な開発プラットフォーム。正しく理解して設定すれば、デュアルブートもクラウドVMも不要で、Windows上にプロダクションレベルのLinux環境が手に入ります。


参考文献


この記事は「わかったつもりになってない?」シリーズの一部です。

No. タイトル 状態
1 Linuxってなんだ? ✅ 公開済み
2 Ubuntuってなんだ? ✅ 公開済み
3 WSLってなんだ?(この記事) ✅ 公開済み
4 Dockerってなんだ? ✅ 公開済み
5 Docker Composeってなんだ? ✅ 公開済み
6 Kubernetesってなんだ? ✅ 公開済み

📌 X(Twitter)でも技術情報を発信しています: @geneLab_999

1
2
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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?