WSL2のUbuntu 22.04でDockerが起動しない問題対応

:::note info
WindowsのWSL2上でDocker Desktopに依存しないDockerをインストールするときに発生する問題です。
急ぎの方は「問題解決」欄をご覧ください。
:::

# 問題再現

## Ubuntu 22.04 インストール

Microsoft Storeからダウンロードできる利用可能な ディストリビューションの一覧を確認します。
Ubuntu 22.04 LTSが利用可能なことが分かります。

```powershell
$ wsl --list --online
NAME               FRIENDLY NAME
Ubuntu             Ubuntu
Debian             Debian GNU/Linux
kali-linux         Kali Linux Rolling
SLES-12            SUSE Linux Enterprise Server v12
SLES-15            SUSE Linux Enterprise Server v15
Ubuntu-18.04       Ubuntu 18.04 LTS
Ubuntu-20.04       Ubuntu 20.04 LTS
Ubuntu-22.04       Ubuntu 22.04 LTS
OracleLinux_8_5    Oracle Linux 8.5
OracleLinux_7_9    Oracle Linux 7.9
```

Ubuntu 22.04のディストリビューションをインストールします。

```powershell
$ wsl --install --distribution Ubuntu-22.04
Enter new UNIX username: ubuntu
New password: ********
Retype new password: ********
```

インストールしたら、すぐUbuntu 22.04ターミナルが起動されますが、別のターミナルでディストリビューションを一覧を表示し、状態とWSLサポートバージョンを確認できます。

```powershell
$ wsl --list --verbose
  NAME                   STATE           VERSION
* Ubuntu-22.04           Running         2
```

## Dockerインストールと起動

こちらで起動しても起動できないことが確認できます。

```bash
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
[sudo] password for ubuntu: ********
$ docker --version
Docker version 23.0.0, build e92dd87
$ sudo service docker start
 * Starting Docker: docker                                                                                       [ OK ]
$ sudo service docker status
 * Docker is not running
$ ps aux | grep docker
ubuntu    ... pts/0    S+   15:00   0:00 grep --color=auto docker
```

# 問題解決

Ubuntu 22.04だとiptables-nftをデフォルトで使うことが原因です。それをiptables-legacyに変更するとDockerは動きます。
Ubuntu 21.10からパケットフィルタリングツールがnftablesに代わりましたが、WSL2上だと問題あることで報告されているようです。

```bash
$ sudo update-alternatives --config iptables
There are 2 choices for the alternative iptables (providing /usr/sbin/iptables).

  Selection    Path                       Priority   Status
------------------------------------------------------------
* 0            /usr/sbin/iptables-nft      20        auto mode
  1            /usr/sbin/iptables-legacy   10        manual mode
  2            /usr/sbin/iptables-nft      20        manual mode

Press <enter> to keep the current choice[*], or type selection number: 1
update-alternatives: using /usr/sbin/iptables-legacy to provide /usr/sbin/iptables (iptables) in manual mode
$ sudo service docker start
 * Starting Docker: docker                                                                                       [ OK ]
$ sudo service docker status
 * Docker is running
$ ps aux | grep docker
root      ... ?       Sl   15:04   0:00 /usr/bin/dockerd -p /var/run/docker.pid
root      ... ?       Ssl  15:04   0:00 containerd --config /var/run/docker/containerd/containerd.toml --log-level info
ubuntu    ... pts/0   S+   15:04   0:00 grep --color=auto docker
$ sudo docker run hello-world
...
Hello from Docker!
...
```

# Docker Compose インストール

```bash
$ sudo apt install -y jq
$ release_version=$(curl -s https://api.github.com/repos/docker/compose/releases | jq -r '.[0] | .tag_name')
$ sudo curl -L "https://github.com/docker/compose/releases/download/${release_version}/docker-compose-$(uname -s | tr 'A-Z' 'a-z')-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
$ docker-compose --version
Docker Compose version v2.24.2
```

# 便利設定

dockerコマンドをsudoなしで実行する。

```bash
sudo usermod -aG docker $USER
```

Ubuntuを起動するさいにdockerも起動する。

```bash
cat << EOF >> ~/.bashrc
if service docker status 2>&1 | grep -q "is not running"; then
  wsl.exe --distribution "${WSL_DISTRO_NAME}" --user root --exec /usr/sbin/service docker start > /dev/null 2>&1
fi
EOF
```