WSL2 Docker Engine と Windows Docker CLI の接続方法

# 概要
この記事は Docker Desktop や Rancher Desktop を使わず Windows から WSL2 の Docker にアクセスする試行錯誤の記録です。この記事で紹介する方法には以下の制約があることにご注意ください。

- **ボリュームマウントの制約**: Windows 側のディレクトリを Docker コンテナにマウントする際、`/mnt/c` の形式で指定する必要があります
- **Docker Desktop や Rancher Desktop の利点**: これらのツールを使用する場合、このようなボリュームマウントに関する制約はなく、より柔軟に利用できます

試行錯誤した結果として最終的に Rancher Desktop を使うことにしました。

後で再度必要になることがあるかもしれないのでここに記録として残します。

# 前提条件
- **WSL2 環境**: Ubuntu 24.04 - systemd 有効済み
- **Docker Engine**: WSL2 の Ubuntu 上でインストール済み
- **Docker CLI**: Windows 上にインストール済み ([公式インストールガイド](https://docs.docker.com/engine/install/binaries/#install-server-and-client-binaries-on-windows), [ダウンロードリンク](https://download.docker.com/win/static/stable/x86_64))

# 手順
## ステップ 1: WSL2 側 - docker.service の設定変更
変更前後の設定内容を以下に示します。

### 変更前

```bash
[Service]
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
```

### 変更後

```bash
[Service]
ExecStart=/usr/bin/dockerd --containerd=/run/containerd/containerd.sock
```

`-H fd://` を削除します。この設定により、WSL2 内の Docker Engine がローカルホストのポート 2375 を通じてアクセス可能になります。以下は設定調整用の `sed` コマンドの例です。

```bash
sudo sed -i 's| -H fd://||' /usr/lib/systemd/system/docker.service
```

## ステップ 2: WSL2 側 - daemon.json の作成
次に `/etc/docker/daemon.json` ファイルを編集し、外部からの接続を許可する設定を行います。新規でファイルを作成するか、既存のものを編集してください。初回インストール時は daemon.json を新規作成してください。

以下のように設定することで、すべてのインターフェースからの接続を許可します。

```json
{
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]
}
```

これにより、Docker デーモンが Unix ソケットとすべてのインターフェースで TCP 接続を受け入れるようになります。次のステップでセキュリティを強化します。

ファイルを保存したら、`systemctl daemon-reload` を実行し、Docker サービスを再起動します。

```bash
sudo systemctl daemon-reload
sudo systemctl restart docker
```

## ステップ 3: WSL2 側 - iptables でアクセス制限を設定
セキュリティ強化のために `iptables` でアクセス制限を行います。

```bash
# ローカルホストからの Docker Engine への接続を許可する。
sudo iptables -A INPUT -p tcp -s 127.0.0.1 --dport 2375 -j ACCEPT
# WSL2 プライベート IP アドレスからの Docker Engine への接続を許可する。
# 許可しないと Docker CLI の内部通信が失敗することがある。例えば docker info でエラーが出る。
# 環境によって調整が必要かもしれない。
sudo iptables -A INPUT -p tcp -s 172.16.0.0/12 --dport 2375 -j ACCEPT
# その他の Docker Engine への接続を拒否する。
sudo iptables -A INPUT -p tcp --dport 2375 -j DROP
```

### iptables の永続化

`iptables` の設定を永続化するために `iptables-persistent` パッケージを使用します。
以下のコマンドを実行してインストールと設定保存を行います。

```bash
# iptables-persistent のインストールダイアログの入力値を事前に設定する。
echo iptables-persistent iptables-persistent/autosave_v4 boolean true | sudo debconf-set-selections
echo iptables-persistent iptables-persistent/autosave_v6 boolean true | sudo debconf-set-selections
# iptables-persistent をインストールする。
sudo apt-get install -y iptables-persistent
# iptables の設定を永続化する。
sudo netfilter-persistent save
```

これにより、再起動後も `iptables` のルールが維持されます。

## ステップ 4: Windows 側 - 環境変数を設定

Windows 側の Docker CLI から WSL2 の Docker Engine にアクセスするために、`DOCKER_HOST` 環境変数を設定します。`DOCKER_HOST` 環境変数は Docker CLI がどのホストの Docker デーモンに接続するかを指定する変数です。

コマンドプロンプトや PowerShell を開き、以下のコマンドを実行してください。

```cmd
setx DOCKER_HOST tcp://localhost:2375
```

## ステップ 5: Windows 側 - 動作確認

Windows のターミナルで Docker CLI コマンドを実行し、正常に動作することを確認します。

```cmd
docker info
```

このコマンドで Docker の情報が表示されれば成功です。WSL2 上の Docker Engine に問題なく接続できています。
`docker info` コマンド実行時に以下の警告が表示されるかもしれません。これは TCP 接続が暗号化されていないためですが無視します。必要な方は暗号化の設定にチャレンジしてみてください

```
[DEPRECATION NOTICE]: API is accessible on http://0.0.0.0:2375 without encryption.
```

以上です。