WSL2上へUbuntuをインストールしてDocker環境を構築する

## ０．ここでやること

- 既にあるWSLとUbuntuのアンインストール
- Microsoft Store版のWSLとUbuntuをインストール
- Windows Termianlのインストール
- systemdの確認
- dockerとdocker composeのインストール

## 1．WSLってなんだ？

[Wikipedia](https://ja.wikipedia.org/wiki/Windows_Subsystem_for_Linux)によると

> **Windows Subsystem for Linux**(**WSL**) とは、[Linux](https://ja.wikipedia.org/wiki/Linux)の（[ELFフォーマット](https://ja.wikipedia.org/wiki/Executable_and_Linkable_Format)形式の）[バイナリ](https://ja.wikipedia.org/wiki/%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA)[実行ファイル](https://ja.wikipedia.org/wiki/%E5%AE%9F%E8%A1%8C%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB)を[Windows 10](https://ja.wikipedia.org/wiki/Microsoft_Windows_10)および[Windows Server](https://ja.wikipedia.org/wiki/Windows_Server)上でネイティブ実行するための[互換レイヤー](https://ja.wikipedia.org/wiki/%E4%BA%92%E6%8F%9B%E3%83%AC%E3%82%A4%E3%83%A4%E3%83%BC)である。
> 

とのことで、Windows上でLinuxを動作させるための仕組みがWSL、そのVersion２がWSL2です。

## 2．WSL2ってなにがいいの？

利点としては以下が挙げられます。

- **軽量で高速起動**
    - 従来のWSLでも動作に必要なメモリが少なく、軽量な動作と起動の速さというメリットがあったが、WSL2では更に強化されている
    - 仮想マシンでLinuxを立ち上げて動作させるよりも軽量で高速
- **完全な互換性**
    - 従来のWSLではLinuxシステムコールを受け取りWindowsのシステムコールに変換していたがその変換が不完全であり度々不具合が報告されていた
    - WSL2よりHyper-Vを利用しLinuxカーネルそのものが動作するため、完全なエミュレーションとなっており、Docker等も問題なく動作するようになった
- **ファイルアクセス速度の向上**
    - 従来のWSLではファイルアクセスが遅い点が指摘されていたが、WSL2より仮想HDDでext4が利用され、直接やり取りができることからアクセス速度が上がった
- **仮想マシン化**
    - 軽量ユーティリティVMを動作させるためにHyper-Vを用いており、OSの縛りがなく導入できる
    - 従来のWSLではWindows上で動作していたため、IPアドレスがWindowsと共通だったが、仮想化する事により仮想ネットワークアダプタが作成される事で別のIPアドレスを割り当てる事が可能になった

つまり、WSLがVersion２なって、これまでの問題が解決され、めっちゃ使いやすくなったってことです。

軽量なのはとっても魅力！！

詳細を知りたい方は[こちら](https://learn.microsoft.com/ja-jp/windows/wsl/compare-versions)を確認してみてください。

## 3．さっそくWSL2をインストールしてみる

### 3 - 1．「Windowsの機能の有効化または無効化」の設定

インストール前に「Windowsの機能の有効化または無効化」の設定を確認します。

検索バーで入力すると画像のように出てくるのでクリック
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091855/448d7e4d-8e48-129b-20aa-eff7877c9c32.png)

「Linux用Windowsサブシステム」「仮想マシンプラットフォーム」の２つにチェックを入れます。
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091855/67f622cd-ecfb-a451-c037-a44e2c470880.png)
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091855/063bcd08-3761-5b3a-6498-9ce949aa213a.png)
OKを押すと、再起動を求められるので再起動します。

### 3 - 2．既にあるWSLやUbuntuのアンインストール

試行錯誤の中で既に一部インストールしてしまってる方もいるかと思うので、ここでアンインストールを行います。

「設定≫アプリ≫アプリと機能」で以下を行う（あればアインストールして下さい）

- 「linux」と検索バーに入力、「Linux用Windowsサブシステム」をアンインストール
- 「linux」と検索バーに入力、「Windows Subsystem for Linux Update」をアンインストール
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091855/dac990cb-a4b5-fbff-be91-c120c1e506aa.png)

- 「ubuntu」と検索バーに入力、「Ubuntu」をアインストール
![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091855/c9b97c27-7386-0954-f5ac-b8e07f70a68b.png)

### 3 - 3．Store版のWSLとUbuntuをインストールする

Microsoft Storeから「Windows Subsystem for Linux」と「Ubuntu」をインストールする
![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091855/eafb584a-4977-2152-ef21-fba174aabfab.png)
![007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091855/a0d3c697-ff59-5c32-6810-c6b981dc0083.png)

### 3 - 4．Ubuntuを開く

先程インストールしたUbuntuを開きます。

以下の表示になればOK！！（エラーの場合は読み進めて頂くと対処方記載しています）

```bash
Installing, this may take a few minutes...
Please create a default UNIX user account. The username does not need to match your Windows username.
For more information visit: https://aka.ms/wslusers
Enter new UNIX username:
```

好きなユーザー名とパスワードを入力します。

```bash
Enter new UNIX username: xxxxxxxxxxx
New password:
Retype new password:
```

以下が表示されてインストール完了です。

```bash
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.10.16.3-microsoft-standard-WSL2 x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

This message is shown once a day. To disable it please create the
/home/{user}/.hushlogin file.
{user}@LAPTOP-xxxxxxxx:~$
```

とりあえずお決まりを実行しておきましょう

```bash
sudo apt update
```

【Ubuntu起動時に以下の様なエラーになった場合】

```bash
ディスク 'C:\Users\ahaya\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\LocalState\ext4.vhdx'を WSL2 に接続できませんでした: 指定されたファイルが見つかりません。
Error code: Wsl/Service/CreateInstance/MountVhd/ERROR_FILE_NOT_FOUND
ディスク 'C:\Users\ahaya\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\LocalState\ext4.vhdx'を WSL2 に接続できませんでした: 指定されたファイルが見つかりません。
Error code: Wsl/Service/CreateInstance/MountVhd/ERROR_FILE_NOT_FOUND
ディスク 'C:\Users\ahaya\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\LocalState\ext4.vhdx'を WSL2 に接続できませんでした: 指定されたファイルが見つかりません。
Error code: Wsl/Service/CreateInstance/MountVhd/ERROR_FILE_NOT_FOUND
Press any key to continue...
```

WSL上のUbuntuが初回起動時に行っている、初期化処理を行うことで解消できます。

`Press any key to continue...`の通り何かキーを押してUbuntuを終了し、PowerShellを開いてください。
![008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091855/78d8497f-d34c-b764-9545-cb6e69392869.png)
PowerShellにて以下を実行し、登録されているディストリビューションを確認します。
この例ではUbuntuのディストリビューションのみが登録されています。

```powershell
PS C:\Users\Name> wsl -l
Linux 用 Windows サブシステム ディストリビューション:
Ubuntu (既定)
```

以下を実行して、Ubuntuのディストリビューションの登録を解除します。

```powershell
PS C:\Users\User> wsl --unregister Ubuntu
登録解除。
この操作を正しく終了しました。
```

再度をUbuntuを開いて`Installing, this may take a few minutes...`と表示さればOKです。

上記手順通りにユーザー名、パスワードの登録と`sudo apt update`を行ってください。

## 4．便利なターミナルで開く

Microsoft Storeにて「Windows Terminal」をダウンロードします（既にある人が多い）
![009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091855/98b047e2-ba7c-0cf2-765c-1f174eccceca.png)
このアプリは画像のようにターミナルをタブで管理できて、PowerShellやコマンドプロンプト、先程インストールしたUbuntuなど一つのウィンドウで色々開くことができます。
![010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091855/1330e19d-ee6f-98bd-f52d-f9094ae36785.png)
設定から既定のプロファイルや既定のターミナルアプリケーションを設定できるので、自分の環境に合わせて設定しましょう。
![011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091855/9312020d-332a-ec2e-45de-533d911cd31d.png)

## 5．systemdが利用可能にする

以下の記事の通り
[https://devblogs.microsoft.com/commandline/systemd-support-is-now-available-in-wsl/](https://devblogs.microsoft.com/commandline/systemd-support-is-now-available-in-wsl/)
「**Windows Subsystem for Linux**」が「**systemd**」に対応しネイティブに動作するようになりました。
以前はGenieなどを入れて動かす必要がありましたが、Store版WSLを利用すれば最初から利用可能です。

### 5 - 1．systemdの有効化
公式の記事にあるとおり、systemdを利用するには`vim /etc/wsl.conf`を実行して以下設定を書くことで有効化できます。既にファイルがある方は以下の通り追記または修正してください。
```vim
[boot]
systemd=true
```

### 5 - 2．動作の確認

念のためここでは以下をUbuntuで実行して動作していることを確認します。
一覧が表示されればOKです。

```bash
systemctl list-units --type=service

# OUTPUT:
# UNIT                                                   LOAD   ACTIVE SUB     DESCRIPTION                 >
# apport.service                                         loaded active exited  LSB: automatic crash report >
# console-getty.service                                  loaded active running Console Getty
# console-setup.service                                  loaded active exited  Set console font and keymap
# cron.service                                           loaded active running Regular background program p>
# dbus.service                                           loaded active running D-Bus System Message Bus
# getty@tty1.service                                     loaded active running Getty on tty1
# keyboard-setup.service                                 loaded active exited  Set the console keyboard lay>
# ︙
```

### 5 - 3．`systemd-sysusers.service`がFailedの場合の対処

同一の事象が起こっている記事があったのでこの通りに修正してみます。
[https://qiita.com/tomo00223/items/970fb22ffbcf15227518](https://qiita.com/tomo00223/items/970fb22ffbcf15227518)

1. 以下を実行
`sudo vi /usr/lib/systemd/system/systemd-sysusers.service`
2. 以下３つをコメントアウト
    
    ```bash
    # LoadCredential=passwd.hashed-password.root
    # LoadCredential=passwd.plaintext-password.root
    # LoadCredential=passwd.shell.root
    ```
    
3. 末尾に以下を追記
`LoadCredential=`
4. PowerShellを開いてwslをシャットダウンして、、、
    
    ```powershell
    wsl.exe --shutdown
    ```
    
5. 再度Ubuntuを開いて、systemctlのサービス一覧を表示してみると、、、
    
    ```powershell
    systemctl list-units --type=service
    # OUTPUT:
    # ︙
    # systemd-sysusers.service                               loaded active exited  Create System Users
    # ︙
    ```
    
    警告が消えました！
    

## 6．Docker環境の構築

### 6 - 1．Dockerってなんだ？

[Wikipedia](https://ja.wikipedia.org/wiki/Docker)によると

> **Docker**（ドッカー[[4]](https://ja.wikipedia.org/wiki/Docker#cite_note-4)）は、コンテナ仮想化を用いて[アプリケーション](https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2)を開発・配置・実行するためのオープンプラットフォームである[[5]](https://ja.wikipedia.org/wiki/Docker#cite_note-5)。
> 
> 
> Dockerはコンテナ仮想化を用いた[OSレベルの仮想化](https://ja.wikipedia.org/w/index.php?title=OS%E3%83%AC%E3%83%99%E3%83%AB%E3%81%AE%E4%BB%AE%E6%83%B3%E5%8C%96&action=edit&redlink=1)（[英語版](https://en.wikipedia.org/wiki/OS-level_virtualisation)）によりアプリケーションを開発・実行環境から隔離し、アプリケーションの素早い提供を可能にする。かつその環境自体をアプリケーションと同じようにコード（イメージ）として管理可能にする[[6]](https://ja.wikipedia.org/wiki/Docker#cite_note-6)。Dockerを開発・テスト・デプロイに用いることで「コードを書く」と「コードが製品として実行される」間の時間的ギャップを大きく短縮できる[[7]](https://ja.wikipedia.org/wiki/Docker#cite_note-7)
> 

とのこと。
コンテナ？ナニソレオイシイノ？って感じですが、説明すると以下の通りです。
Virtual Machine（所謂VM）は画像の左側、コンテナは右側になります。
![012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091855/1120bb82-7b63-eccf-6817-64a57847985f.png)
（[https://knowledge.sakura.ad.jp/13265/](https://knowledge.sakura.ad.jp/13265/)より引用）

> VirtualBoxなどの仮想マシンでは、ホストマシン上でハイパーバイザを利用しゲストOSを動かし、その上でミドルウェアなどを動かします。
それに対し、コンテナはホストマシンのカーネルを利用し、プロセスやユーザなどを隔離することで、あたかも別のマシンが動いているかのように動かすことができます。
また、Dockerはミドルウェアのインストールや各種環境設定をコード化して管理します。
> 

それによっての生まれる利点が次になります。

### 6 - 2．Dockerって何がいいの？

Dockerの利点として以下が挙げられます。

1. コード化されたファイルを共有することで、どこでも誰でも同じ環境が作れる。
2. 作成した環境を配布しやすい。
3. スクラップ＆ビルドが容易にできる。

ひとりで開発するならDockerである必要はないかもしれませんが、複数人で開発を行う場合、Macを使うの人もいればWindowsの人もいます。
Windowsの中でVMを使う人もいればWSLを使う人もいます。
そういった異なる環境下でも全く同じ動作環境を構築することができるのはとんでもない利点です。
他にも環境が汚れないことや、PCのリソースを食いにくい点も利点かもしれません。

### 6 - 3．DockerとDocker-CEの違い

DockerとDocker-CEの違いについては以下記事を参照してみてください。
[https://qiita.com/s-suefusa/items/cb3c4044da3b3657dbd0](https://qiita.com/s-suefusa/items/cb3c4044da3b3657dbd0)

基本的には同じものと考えてよいです。
Docker-CEを使っていれば間違いないとのこと。

### 6 - 4．Docker-CEのインストール

Docker-CEをインストールしていきます。

```bash
#既存のパッケージのリストを更新
sudo apt update
#aptがHTTPS経由でパッケージを使用できるようにするいくつかの必要条件パッケージをインストール
sudo apt install apt-transport-https ca-certificates curl software-properties-common
```

公式DockerリポジトリのGPGキーをシステムに追加する方法として`apt-key add`を行う方法もありますが、`apt update`した際に以下のような警告が表示されます。（Ubuntu22.04までのバージョンのみ）

```bash
# OUTPUT:
# W: https://download.docker.com/linux/ubuntu/dists/focal/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.
```

[Ubuntuマニュアル](https://manpages.ubuntu.com/manpages/jammy/ja/man8/apt-key.8.html)に以下記載があります。

> [apt-key](https://manpages.ubuntu.com/manpages/jammy/ja/man8/apt-key.8.html)(8) will last be available in Debian 11 and Ubuntu 22.04.

パッケージ管理ツールの APT でパッケージへの電子署名用 OpenPGP 公開鍵を管理する apt-key コマンドが非推奨になっており、更に [Debian](https://www.debian.org/) 12 では apt-key コマンドは削除されます。

つまりは「サードパーティの公開鍵を管理する仕組みは提供するので、自分でやってください。APT では管理しません」ということ。

**【対処法】**

 `/etc/apt/keyrings` ディレクトリに公式DockerリポジトリのGPGキーを `ASCII Armor 形式`で追加します。

```bash
cd /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o docker-key.asc
```

以下コマンドで`archive_uri-https_download_docker_com_linux_ubuntu-jammy.list`を編集します。

```bash
sudo vim /etc/apt/sources.list.d/archive_uri-https_download_docker_com_linux_ubuntu-jammy.list
```

画像の通り、既存の`deb ~~~`の記載をコメントアウトして以下をコピーして下部へ追加し保存して閉じる。

```
deb [arch=amd64 signed-by=/etc/apt/keyrings/docker-key.asc] https://download.docker.com/linux/ubuntu jammy stable
```
![013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091855/45e6e086-8cb1-215b-b7b3-1775caaa4070.png)
再び以下を実行してみる

```bash
sudo apt update
# OUTPUT:
# ︙
# Reading package lists... Done
# Building dependency tree... Done
# Reading state information... Done
# 41 packages can be upgraded. Run 'apt list --upgradable' to see them.
```
警告は表示されてなければOKです！！

続いて、以下を順に実行してDocker-CEをインストールします。

```bash
#Dockerリポジトリからインストールしようとしていることを確認
apt-cache policy docker-ce
#Dockerをインストール
sudo apt install docker-ce
#実行を確認（active  (running)となってればOK）
sudo systemctl status docker
```

これでDockerのインストールは完了です。

### 6 - 5．sudoなしでDockerコマンドを実行可能にする

ここではdockerユーザーグループにuserを追加します。

```bash
#ユーザーをdockerグループに追加
sudo usermod -aG docker ${USER}
#追加を反映
su - ${USER}
#確認（outputにdockerがあればOK）
id -nG
```

### 6 - 6．Docker Hubからイメージをダウンロードできるか確認

以下を順に実行してください。

```bash
docker run hello-world

#OUTPUT:
##Unable to find image 'hello-world:latest' locally
##latest: Pulling from library/hello-world
##0e03bdcc26d7: Pull complete
##Digest: sha256:6a65f928fb91fcfbc963f7aa6d57c8eeb426ad9a20c7ee045538ef34847f44f1
##Status: Downloaded newer image for hello-world:latest
##
##Hello from Docker!
##This message shows that your installation appears to be working correctly.
##...

#ダウンロードしたイメージ確認
docker images
#イメージを強制削除
## docker rmi -f hello-world:latestなど
docker rmi -f {REPOSITORY_NAME}
```

## 7．Docker Composeのインストール

### 7 - 1．docker-composeとの違い

Dockerのサブコマンドであるcomposeと似たものでdocker-composeコマンドが存在します。
その違いは以下の通りです。

> 後発の compose サブコマンドは docker-compose コマンドの将来的な置き換えを目指して開発された機能になるそうです。
> 
> 
> docker-compose は [python](http://d.hatena.ne.jp/keyword/python) で書かれたものですが、compose サブコマンドは compose-[cli](http://d.hatena.ne.jp/keyword/cli) というレポジトリーで Go で再実装されています。
> 
> 互換性を維持した状態で開発されています。ここでいう互換性というのは、docker-compose 側で使えるオプションコマンドや実行方法などが同じような状態で使えるようにされています。
> 
（[https://keyno63.hatenablog.com/entry/2021/07/24/231528](https://keyno63.hatenablog.com/entry/2021/07/24/231528) より引用）

docker-compose の後に compose サブコマンドが再開発され、compose サブコマンドは以前とほぼ同様の使用感になっているようなので、今回はDockerのサブコマンドであるcomposeのインストールを行います。

### 7 - 2．dockerのサブコマンドcomposeのインストール

以下を順に実行し、バージョンが表示されればインストール完了です。

```bash
#既存のパッケージのリストを更新
sudo apt update
#Docker Compose をインストール
sudo apt install docker-compose-plugin
#Version確認
docker compose version
#OUTPUT
#Docker Compose version vx.xx.x
```

## 8．終わり

以上でWSL・Ubuntuのインストール、Docker環境の構築完了です！
ありがとうございました！