WSLにdockerをインストールする手順

Linux環境だと簡単に入るので同じように出来るかと思ったら意外と大変だったのでメモを残しておきます。最短手順を書いているページはたくさんあるので、どうつまづいて何が原因でというのを1つずつメモしておきたいと思います


## 1. WSLをインストールする


まずWindowsでWSLを使えるようにします
PowerShellから1行書くだけです


```powershell:powershell
wsl --install
```


以前はWindowsの設定内になる「Windowsの機能の有効化または無効化」からWSLを有効にして、カーネル更新プログラムパッケージを適用して、と面倒な手順があったんですがWSL2から？簡単になったようです。やったぜ
https://qiita.com/studio_haneya/items/4e640d54090a4526fb37


## 2. WSL用Linuxをインストールする


今回はUbuntu22.04を使いたいので以下はそれを前提に書いていきます


### 2-1. 既に入っているUbuntuを使う


上記のwsl --installからインストールした場合はデフォルトでUbuntuがインストールされますのでWindowsのスタートメニューから起動できます


### 2-2. CLIからインストールする


WSLにインストール可能なディストリビューション一覧を確認します


```powershell:powershell
> wsl --list --online
NAME                                   FRIENDLY NAME
Ubuntu                                 Ubuntu
Debian                                 Debian GNU/Linux
kali-linux                             Kali Linux Rolling
Ubuntu-18.04                           Ubuntu 18.04 LTS
Ubuntu-20.04                           Ubuntu 20.04 LTS
Ubuntu-22.04                           Ubuntu 22.04 LTS
OracleLinux_7_9                        Oracle Linux 7.9
OracleLinux_8_7                        Oracle Linux 8.7
OracleLinux_9_1                        Oracle Linux 9.1
openSUSE-Leap-15.5                     openSUSE Leap 15.5
SUSE-Linux-Enterprise-Server-15-SP4    SUSE Linux Enterprise Server 15 SP4
SUSE-Linux-Enterprise-15-SP5           SUSE Linux Enterprise 15 SP5
openSUSE-Tumbleweed                    openSUSE Tumbleweed
```


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


```powershell:powershell
wsl --install -d Ubuntu-22.04
```


ディストリビューションを起動するのもCLIからできます


```powershell:powershell
wsl -d Ubuntu-22.04
```


その他詳しくは以下公式を参照しましょう
https://learn.microsoft.com/ja-jp/windows/wsl/basic-commands


個人ページだとここが分かりやすいと思います
https://www.tohoho-web.com/ex/wsl.html


### 2-3. Microsoft Storeからインストールする


Microsoft Storeからインストールする事もできます
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/c6903788-679e-9764-6b11-0307046c44b3.png" width=50%>


## 3. WSLのバージョンを上げる


### 3-1. バージョンを確認する


WSL2でないとdockerを使うのが困難なのでバージョンを確認します
https://learn.microsoft.com/ja-jp/windows/wsl/compare-versions
https://qiita.com/omu_kato/items/f9a6b5a02e25f5f2a487


```terminal:コマンドプロンプトまたはpowershell
wsl -l -v
```


```terminal:バージョンが1になっている
  NAME                   STATE           VERSION
  Ubuntu-22.04           Running         1
```


上のようになっている場合はバージョンを上げてやる必要があります


### 3-2. バージョンを上げる


以下のコマンドで対象ディストリビューションのバージョンを変更できます


```terminal:コマンドプロンプトまたはpowershell
wsl --set-version Ubuntu-22.04 2
```


```terminal:バージョンが2になっている
  NAME                   STATE           VERSION
  Ubuntu-22.04           Stopped         2
```


### 3-3. デフォルトのバージョンを指定する


また、デフォルトバージョンを指定しておけば、次回以降インストールした時点で指定のバージョンにしてくれます


```terminal:コマンドプロンプトまたはpowershell
wsl --set-default-version 2
```


## 4. dockerのインストール


WSLにdockerをインストールするにはGPG鍵を使えるようにする必要があります


### 4-1. そのままインストールしようとした場合


dockerのダウンロードにGPG鍵が必要なので、そのままインストールしようとしてもpackageが見つかりません


```terminal:WSL/Ubuntu-22.04/terminal
$ sudo apt-get install docker-ce
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package docker-ce
```


### 4-2. 必要なライブラリをインストールする


dockerをhttpsでインストールする為に必要なライブラリをインストールします


```terminal:WSL/Ubuntu-22.04/terminal
sudo apt-get install ca-certificates curl gnupg lsb-release
```


### 4-3. GPG鍵を登録する


dockerのGPG鍵を登録します


```terminal:WSL/Ubuntu-22.04/terminal
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```


これでやっとインストール出来るようになりました


### 4-4. dockerをインストールする


dockerほか諸々をインストールします


```terminal:WSL/Ubuntu-22.04/terminal
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
```


入っているか確認しましょう


```terminal:WSL/Ubuntu-22.04/terminal
$ docker --version
Docker version 25.0.0, build e758fe5
```


インストールできました


## 5. dockerを起動する


ここでそのままdocker runするとdockerのdaemonがいないと言われます


```terminal:WSL/Ubuntu-22.04/terminal
$ docker run hello-world
docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?.
See 'docker run --help'.
```


dockerが動いているならdocker.logがある筈ですがファイル自体見つからないので、どうやら起動していないようです


```terminal:WSL/Ubuntu-22.04/terminal
$ sudo cat /var/log/docker.log
cat: /var/log/docker.log: No such file or directory
```


インストールしただけでは起動していないのが原因なので起動します


```terminal:WSL/Ubuntu-22.04/terminal
sudo service docker start
```


## 6. permissionを与える


ここでdocker runしようとすると、今度はpermissionがないと言われます


```terminal:WSL/Ubuntu-22.04/terminal
$ docker run hello-world
docker: permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/create": dial unix /var/run/docker.sock: connect: permission denied.
```


/var/run/docker.sockはdockerグループに属しているファイルですので、ログインユーザーをdockerグループに加えてやればpermissionがもらえます


```terminal:WSL/Ubuntu-22.04/terminal
$ ll /var/run/
srw-rw----  1 root docker    0 Jan 20 18:54 docker.sock=
```


以下のusernameを自分のユーザー名に書き換えて実行すればOKです


```terminal:WSL/Ubuntu-22.04/terminal
sudo usermod -aG docker username
```


## 7. iptablesの設定を古いものに変更する


ここでdocker runしようとすると「5. dockerを起動する」で見たのと同じ、dockerのdaemonが見つからないというエラーメッセージが出ます


```terminal:WSL/Ubuntu-22.04/terminal
$ docker run hello-world
docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?.
```


dockerが起動しているか確認すると先程と異なり起動しているようです


```terminal:WSL/Ubuntu-22.04/terminal
$ sudo service docker status
 * Docker is running
```


docker自体は起動しているのでdocker.logを読むと、networkコントローラーの初期化に失敗していると言っています


```terminal:WSL/Ubuntu-22.04/terminal
$ sudo cat /var/log/docker.log
failed to start daemon: Error initializing network controller: 
error obtaining controller instance: failed to register "bridge" driver: 
unable to add return rule in DOCKER-ISOLATION-STAGE-1 chain:  
(iptables failed: iptables --wait -A DOCKER-ISOLATION-STAGE-1 -j RETURN: 
iptables v1.8.7 (nf_tables):  RULE_APPEND failed (No such file or directory): 
rule in chain DOCKER-ISOLATION-STAGE-1
```


これは、WSL2が<a href="https://remix-yh.net/2281/">nftablesに対応していない為にUbuntu-22以降で発生するエラー</a>であるので、iptables-legacyを使うように変更してやります


```terminal:WSL/Ubuntu-22.04/terminal
sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
```


## 8. 完成


ここまでの手順が上手くいっていればdockerが動くようになった筈です


```terminal:WSL/Ubuntu-22.04/terminal
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c1ec31eb5944: Pull complete
Digest: sha256:4bd78111b6914a99dbc560e6a20eab57ff6655aea4a80c50b0c5491968cbc2e6
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
```


やったね


## まとめ


多数の手順が必要であるのに加えて、断片的にそれぞれの問題について書いている記事が多く結構苦戦しました。せっかく書いても少し経つとまた必要な手順が変わりそうに思えますが、少なくとも現時点ではこれで動きましたというメモとして残しておきます