WSL2(Windows Subsystem for Linux 2)とは、Windows上でMicrosoftが提供する本物のLinuxカーネルを軽量な仮想マシンとして動かし、Ubuntuなどのディストリビューションを通常のWindowsアプリと並べて使える仕組みです。Docker Engineやsystemdがそのまま動くため、サーバーで使うのと同じ手順を手元のWindows PCで再現できます。
前提はWindows 11(BIOS/UEFIで仮想化支援が有効)と管理者権限です。Ubuntu 24.04を入れ、systemdとDocker Engineを動かし、.wslconfigでリソースを絞り、exportでバックアップするところまでを扱います。
この記事でわかること
- WSL1(システムコール変換)とWSL2(Hyper-V上の実カーネル)の違いと、ファイルI/Oやdockerへの影響
wsl --installからUbuntu 24.04の導入、/etc/wsl.confでのsystemd有効化/mnt/c越しのI/Oが遅い理由と、プロジェクトをLinux側(ext4)に置く運用- Docker Desktopとの違い(ライセンス・GUI・統合)と、WSL内にDocker Engineを直接入れる手順
.wslconfigのmemory=/processors=、localhostForwarding、export/importによるバックアップ
WSL2とは:WSL1との違いと仕組み
WSL1はLinuxのシステムコールをWindowsカーネルの呼び出しに変換する互換レイヤーで、Linuxカーネルそのものは存在しません。WSL2はHyper-Vの軽量ユーティリティVMの中でMicrosoftがビルドしたLinuxカーネルを起動し、その上でディストリビューションを動かします。VMといっても起動は数秒で、Windows Terminalのタブとして見えます。この構造の違いが、下の表のとおりファイルI/Oとネットワークの特性を決めています。
| 観点 | WSL1 | WSL2 |
|---|---|---|
| Linuxカーネル | なし(システムコール変換) | あり(Hyper-V上の軽量VM) |
| Docker Engine | 動かない | 動く(cgroup、iptablesに対応) |
| Linux側(ext4)のファイルI/O | NTFS上に保持されるため遅い | 仮想ディスクext4.vhdxで高速 |
/mnt/c経由のWindowsファイルI/O | ネイティブに近い | 9Pプロトコル経由で遅い |
| ネットワーク | Windowsと共有 | 既定はNATで別IP(mirroredモードで共有可) |
| メモリ | Windowsと共有 | VMに割当。上限は.wslconfigで指定 |
WSL2を有効化してUbuntu 24.04をインストールする
wsl --install -d Ubuntu-24.04
# 再起動後にUbuntuが起動し、UNIXユーザー名とパスワードを設定する
wsl --list --online # 導入できるディストリビューション一覧
wsl --list --verbose # VERSION列が 2 であること
wsl --update # WSL本体とカーネルの更新
wsl --versionwsl --installは「仮想マシンプラットフォーム」機能の有効化、WSL本体、指定したディストリビューションの導入を一括で行います。執筆時点ではWSL本体がWindowsの機能から切り離されてMicrosoft Store経由で配布されており、wsl --updateでカーネルとツール群が更新されます。wsl --versionでWSL バージョン: 2.x.xのように出れば、この新しい配布形態です。
[boot]
systemd=true
[automount]
options = "metadata"systemd=trueはDocker Engineやsnapのようにsystemdを前提とするサービスに必要で、保存後にPowerShellでwsl --shutdownしてVMを止めると次回起動から有効になります。automountのmetadataは/mnt/c配下のファイルにLinuxのパーミッションを持たせるオプションで、Windows側に置いたSSH鍵をchmod 600したいときに必要です。
ファイルの置き場所とパフォーマンス
Linux側のファイルは仮想ディスクext4.vhdxに入り、Windowsのドライブは/mnt/cとして9Pプロトコルでマウントされます。境界を跨ぐたびにプロトコル変換が入るため、node_modulesや.gitのように小さなファイルを大量に読み書きする操作は/mnt/c上だと桁違いに遅くなります。判断基準は「git、npm、docker、pythonなどLinuxのツールで扱うプロジェクトは~/以下、Wordやブラウザで扱うファイルはWindows側」です。
Linux側のファイルはエクスプローラーから\\wsl.localhost\Ubuntu-24.04\home\ユーザー名で開け、WSLのシェルでexplorer.exe .と打つとカレントディレクトリが開きます。逆にWindowsの実行ファイルはWSLからcode .やnotepad.exeのように呼べます。Gitはどちら側にもありますが、改行コード(core.autocrlf)とファイルモードの扱いが違うので、1つのリポジトリは片側だけで操作します。
ext4.vhdxはファイルを消しても自動では縮みません。執筆時点のWSLではwsl --manage Ubuntu-24.04 --set-sparse trueでスパースVHDにすると空き領域が返却されるようになります。Cドライブの空きが減り続けるときは、まずここを疑ってください。
Docker:WSL内のDocker EngineとDocker Desktopの違い
| 観点 | Docker Desktop(WSL2バックエンド) | WSL内のDocker Engine |
|---|---|---|
| ライセンス | 企業規模によって有料サブスクリプションが必要(条件は執筆時点でも変更があるため公式の利用規約を確認) | Apache 2.0のOSS。無料 |
| GUI・付属機能 | ダッシュボード、設定画面、Kubernetes同梱 | CLIのみ。設定は/etc/docker/daemon.json |
| Windows側からのdocker CLI | 自動で統合される | WSLのシェルから使う(wsl docker psでも可) |
| 起動 | Windowsログオン時に常駐 | systemdが起動。WSLが止まっていれば動かない |
| 更新 | Desktopの更新機能 | apt upgrade |
会社のPCでライセンス条件が確認できない場合、またはCLIだけで困らない場合は、WSL内のDocker Engineを勧めます。GUIで複数コンテナの状態を眺めたい、Windows側のIDEからdockerを直接呼びたい、Kubernetesをワンクリックで欲しい、という場合はDocker Desktopのほうが楽で、その場合はSettings → Resources → WSL integrationで使うディストリビューションをオンにします。両方を同時に入れるとdockerソケットの取り合いで混乱するので、どちらかに決めてください。
sudo apt-get update && sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update && sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker "$USER" && newgrp docker
docker run --rm hello-world手順はサーバーのUbuntuとまったく同じで、compose.yamlもそのまま使えます。詳しい使い方はDocker Compose入門を参照してください。WSLは最後のシェルを閉じてしばらくするとVMごと停止するため、常時動かしたいコンテナがあるならrestart: unless-stoppedを付けたうえで、WSLの自動停止を止める[boot]のcommand=やタスクスケジューラで起動する方法を検討します。
VS Codeとの連携
Windows側のVS Codeに「WSL」拡張機能を入れ、WSLのシェルでプロジェクトのディレクトリへ移動してcode .と打つと、UIはWindowsで、拡張機能・ターミナル・言語サーバーはWSL側のVS Code Server(~/.vscode-server)で動く分離構成になります。pythonやgitのパスも自動でLinux側が使われ、Windowsに別途ツールを入れる必要はありません。仕組みはRemote SSHと同じで、VS CodeのRemote SSHとDev Containersで詳しく扱っています。
ネットワークとポート:localhostForwarding
既定のNATモードでは、WSL2のVMはWindowsとは別のIPアドレス(172.x.x.xなど、起動ごとに変わる)を持ちます。それでもWindowsのブラウザからhttp://localhost:3000でWSL内のサーバーに届くのは、localhostForwarding(既定でtrue)がWindows側のlocalhostへの接続をWSLへ転送しているからです。逆方向(WSLからWindows上のサービスへ)はlocalhostでは届かず、ip routeで見えるデフォルトゲートウェイ(Windows側の仮想NICのIP)を使います。
LAN内の別の端末やスマートフォンからWSL内のサーバーへ繋ぎたい場合、NATモードではnetsh interface portproxyでWindows側のポートをWSLのIPへ転送する必要があり、IPが変わるたびに再設定になります。Windows 11 22H2以降では.wslconfigにnetworkingMode=mirroredを書くと、WSLがWindowsと同じネットワークインターフェースとIPを共有し、この手間がなくなります(執筆時点)。
メモリ・CPUの制限:.wslconfig
[wsl2]
memory=8GB
processors=4
swap=2GB
localhostForwarding=true
# Windows 11 22H2以降。LANの他端末から直接届く必要があるときだけ
# networkingMode=mirrored
[experimental]
autoMemoryReclaim=gradual
sparseVhd=true.wslconfigは全ディストリビューション共通のVM設定で、/etc/wsl.conf(ディストリビューションごと)とは別物です。既定ではWSL2はホストメモリの一定割合(執筆時点では50%が上限。正確な値は公式ドキュメント参照)まで使い、Linux側のページキャッシュが解放されないため、Windowsのタスクマネージャーでは「Vmmem」がメモリを食い続けているように見えます。memory=で上限を切り、autoMemoryReclaim=gradualでアイドル時にキャッシュを返させるのが対策です。変更はwsl --shutdownのあと次回起動から効きます。
バックアップとエクスポート
wsl --shutdown
wsl --export Ubuntu-24.04 D:\wsl-backup\ubuntu-2404.tar
# 復元(別PCや作り直し時)。名前とvhdxの置き場所を指定する
wsl --import Ubuntu-dev D:\wsl\Ubuntu-dev D:\wsl-backup\ubuntu-2404.tar --version 2
# importした環境はrootで起動するため、既定ユーザーを戻す
wsl -d Ubuntu-dev -u root -- sh -c 'printf "[user]\ndefault=%s\n" myuser >> /etc/wsl.conf'--exportはディストリビューション全体をtarにするので、Docker用のイメージやキャッシュを抱えたままだと数十GBになります。docker system prune -aしてから取るか、プロジェクトはGitに、DBはダンプにと分けて考えると軽く済みます。--importは同じtarから何個でも複製できるため、「設定済みの環境を新しいPCへ移す」「検証用に使い捨ての複製を作る」用途に向いています。
wsl --unregister Ubuntu-24.04は確認なしにext4.vhdxごと即座に削除します。作り直す前に必ず--exportを取り、Linux側の~/に置いたコードがGitにpush済みかを確認してください。
動作確認
PS> wsl -l -v
NAME STATE VERSION
* Ubuntu-24.04 Running 2
$ systemctl is-system-running
running # 一部ユニットが失敗していれば degraded(systemd自体は動作)
$ docker compose version
Docker Compose version v2.xx.x
$ grep MemTotal /proc/meminfo
MemTotal: 8xxxxxx kB # .wslconfig の memory= が反映されている
$ python3 -m http.server 8000
# Windowsのブラウザで http://localhost:8000 が開けば localhostForwarding が効いているつまずきポイント
| 症状・エラーメッセージ | 原因 | 対処 |
|---|---|---|
WslRegisterDistribution failed with error: 0x80370102 | BIOS/UEFIで仮想化支援(Intel VT-x / AMD-V)が無効、または「仮想マシンプラットフォーム」機能がオフ | ファームウェアで有効化し、管理者PowerShellでEnable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform |
Temporary failure resolving 'archive.ubuntu.com'(apt) | DNSが引けない。VPNクライアントが/etc/resolv.confの自動生成と衝突していることが多い | /etc/wsl.confに[network] generateResolvConf=falseを書き、/etc/resolv.confに社内DNSか公開DNSを固定してwsl --shutdown |
System has not been booted with systemd as init system (PID 1). Can't operate. | [boot] systemd=trueがない、または書いた後にVMを再起動していない | /etc/wsl.confを修正してwsl --shutdown |
Cannot connect to the Docker daemon at unix:///var/run/docker.sock | dockerサービスが起動していない、またはDocker DesktopのWSL integrationがこのディストリビューションでオフ | sudo systemctl status dockerで確認し起動。Desktop利用時はintegrationをオン |
よくある質問
WSL2とDocker Desktopはどちらを使う?
CLIで運用でき、会社のライセンス条件を確認する手間を避けたいならWSL内のDocker Engineです。GUIのダッシュボード、Windows側IDEとの統合、同梱のKubernetesが欲しいならDocker Desktopで、企業利用の条件は公式の利用規約で確認してください。どちらもコンテナ自体はWSL2のVM上で動くため、性能差はほとんどありません。
WSL2は重いですか?
Linux側(ext4)で作業する限り、ネイティブLinuxに近い速度です。重く感じる原因の大半は、プロジェクトを/mnt/cに置いて9P経由でアクセスしていること、または上限未設定のメモリをページキャッシュが占有していることで、置き場所の変更と.wslconfigのmemory=で解決します。
Windows側のファイルを編集できますか?
できます。Cドライブは/mnt/cとしてマウントされ、読み書きともに可能です。ただしパーミッションを扱うには/etc/wsl.confのautomountにoptions = "metadata"が必要で、大量の小さなファイルを扱う処理は遅くなります。開発対象のリポジトリはLinux側に置き、Windowsからは\\wsl.localhost\経由で開くのが基本です。
まとめ
WSL2はHyper-V上の実カーネルなので、Docker Engineとsystemdをサーバーと同じ手順で動かせます。運用の要点は3つで、プロジェクトは~/(ext4)に置いて/mnt/cを跨がない、.wslconfigのmemory=とautoMemoryReclaimでVmmemの肥大化を抑える、作り直す前にwsl --exportを取る。Docker Desktopは必要になった時点で検討すれば十分で、まずはWSL内のEngineで始めるのが手戻りの少ない選択です。
次に読む
- GitHub Actionsで始めるCI/CD:手元で動いたcompose.yamlをpushからデプロイまで自動化する
- Claude Codeとは?ターミナルで動くAIコーディングエージェント:WSL2のターミナルからそのまま使えるAIエージェント