本文へ移動
購読
GUIDE#devtools更新 2026.09.24

WSL2とDockerで作るWindows開発環境:インストールから日常運用のコツまで

wsl --installからUbuntuの導入、systemd有効化、WSL内へのDocker Engine導入とDocker Desktopとの違い、/mnt/cが遅い理由、.wslconfigのメモリ制限まで。

level
初級
time
約25分
stack
Windows 11 / WSL2 / Ubuntu 24.04 / Docker
author
@ryoma_t
// 前提条件
Windows 11のPC(BIOS/UEFIで仮想化支援が有効)/ 管理者権限 / Linuxシェルの基本操作

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とネットワークの特性を決めています。

観点WSL1WSL2
Linuxカーネルなし(システムコール変換)あり(Hyper-V上の軽量VM)
Docker Engine動かない動く(cgroup、iptablesに対応)
Linux側(ext4)のファイルI/ONTFS上に保持されるため遅い仮想ディスクext4.vhdxで高速
/mnt/c経由のWindowsファイルI/Oネイティブに近い9Pプロトコル経由で遅い
ネットワークWindowsと共有既定はNATで別IP(mirroredモードで共有可)
メモリWindowsと共有VMに割当。上限は.wslconfigで指定

WSL2を有効化してUbuntu 24.04をインストールする

PowerShell(管理者)
wsl --install -d Ubuntu-24.04
# 再起動後にUbuntuが起動し、UNIXユーザー名とパスワードを設定する
wsl --list --online        # 導入できるディストリビューション一覧
wsl --list --verbose       # VERSION列が 2 であること
wsl --update               # WSL本体とカーネルの更新
wsl --version

wsl --installは「仮想マシンプラットフォーム」機能の有効化、WSL本体、指定したディストリビューションの導入を一括で行います。執筆時点ではWSL本体がWindowsの機能から切り離されてMicrosoft Store経由で配布されており、wsl --updateでカーネルとツール群が更新されます。wsl --versionでWSL バージョン: 2.x.xのように出れば、この新しい配布形態です。

/etc/wsl.conf(Ubuntu側)
[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ソケットの取り合いで混乱するので、どちらかに決めてください。

terminal(WSLのUbuntu。systemd有効化後)
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

%UserProfile%\.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のあと次回起動から効きます。

バックアップとエクスポート

PowerShell
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済みかを確認してください。

動作確認

terminal
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: 0x80370102BIOS/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.sockdockerサービスが起動していない、または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で始めるのが手戻りの少ない選択です。

次に読む

$ subscribe --weekly
毎週月曜、企業ITとホームラボの要点を5分で。