WSL2：もっと！docker-cliのインストール手順決定版はこれだ(Windows11/Ubuntu24.04)

# このページの手順でできること

:::note
- WSL2(systemd有効)を利用できる
- docker-cliをインストールできる
- コンテナを実行できる
:::

# 早速やってみよう

## WSL2のインストール

### 開始する前に：前提条件を確認する

:::note warn
- 前提条件
  - Winsows11(22H2以降、最新のUpdate適用済)であること
  - 「仮想化」が有効であること(タスクマネージャーから確認可能)
  - **使用するUbuntuのバージョンが24.04以降**であること
:::

- 「仮想化」が有効になっていない場合
  - 物理PCの場合、UEFIの設定から「VT-x」あるいは「Intel Virtualization Technology」を有効にする
  - クラウドIaaS環境の場合、**入れ子になった仮想化**が有効なインスタンスタイプを選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161516/5472341e-3651-7138-0f4c-16cfb67f0de3.png)

### 事前準備：user-data(cloud-init定義ファイル)の配置

以下のファイルを、`%USERPROFILE%\.cloud-init\Ubuntu.user-data` に保存する


```powershell
cat .cloud-init/Ubuntu.user-data
```

<details><summary>配置場所確認コマンド(配置内容が出力されていたら正しい)</summary>

```powershell
# powershell起動直後に下記を実行
cat .cloud-init/Ubuntu.user-data
```

</details>


```yaml:Ubuntu.user-data#cloud-config
#cloud-config

package_update: true
package_upgrade: true

timezone: Asia/Tokyo
locale: en_US.UTF-8

users:
  # WSLは、最低1つのrootでないユーザを作成する必要がある
  - lock_passwd: true
    name: dummy

write_files:
  # rootユーザで開始できるようにする
- path: /etc/wsl.conf
  append: true
  content: |
    [user]
    default=root
- path: /home/root/.bashrc
  append: true
  content: |
    # configured by cloud-init
    # export http_proxy=http://proxy.example.com:9999
    # export https_proxy=http://proxy.example.com:9999
- path: /etc/systemd/system/docker.service.d/override.conf
  append: true
  content: |
    [Service]
    #Environment="http_proxy=http://proxy.example.com:9999"
    #Environment="https_proxy=http://proxy.example.com:9999"

apt:
  preserve_sources_list: true
  #http_proxy: http://proxy.example.com:9999
  #https_proxy: http://proxy.example.com:9999

runcmd:
  # - export http_proxy=http://proxy.example.com:9999
  # - export https_proxy=http://proxy.example.com:9999
  # https://docs.docker.com/engine/install/ubuntu/
  # Set up Docker's apt repository.
  - install -m 0755 -d /etc/apt/keyrings
  - curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
  - chmod a+r /etc/apt/keyrings/docker.asc
  - echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list
  - apt-get update
  # Install the Docker packages.
  - apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  # https://docs.docker.com/engine/install/linux-postinstall/#configure-docker-to-start-on-boot-with-systemd
  # Configure Docker to start on boot with systemd
  - systemctl enable docker.service
  - systemctl enable containerd.service
  - systemctl restart docker.service
```

### WSL2の有効化

:::note
WSL2が既に有効の場合は、省略可能。
:::

```powershell
# WSL2を有効化する。まだUbuntuをインストールしない。
wsl --install --no-distribution
wsl --update

# Microsoft Storeが使用できない場合、--web-downloadオプションを付ける。
# wsl --install --no-distribution --web-download
```

### WSL2(Ubuntu24.04)のインストール

```powershell
# Ubuntuをインストール。cloud-initの初期化時間を設けるために --no-launchをつける
wsl --install --distribution Ubuntu --no-launch
# Microsoft Storeが使用できない場合、--web-downloadオプションを付ける。
# wsl --install --distribution Ubuntu --web-download --no-launch

# cloud-initをプロビジョニングする。--waitにより完了を待つことができる
wsl -d Ubuntu -u root exec cloud-init status --wait --format json
```

<details><summary>成功時の出力例</summary>

```
PS C:\Users\aruki> wsl -d Ubuntu -u root exec cloud-init status --wait --format json
{
  "boot_status_code": "enabled-by-generator",
  "datasource": "wsl",
  "detail": "DataSourceWSL",
  "errors": [],
  "extended_status": "done",
  "init": {
    "errors": [],
    "finished": 20.36,
    "recoverable_errors": {},
    "start": 19.46
  },
  "init-local": {
    "errors": [],
    "finished": 19.2,
    "recoverable_errors": {},
    "start": 19.07
  },
  "last_update": "Thu, 01 Jan 1970 00:01:37 +0000",
  "modules-config": {
    "errors": [],
    "finished": 22.14,
    "recoverable_errors": {},
    "start": 20.81
  },
  "modules-final": {
    "errors": [],
    "finished": 97.81,
    "recoverable_errors": {},
    "start": 22.39
  },
  "recoverable_errors": {},
  "stage": null,
  "status": "done"
}
```

</details>

:::note warn

万一エラーになった場合、下記の方法で登録解除する

```powershell
wsl --unregister Ubuntu
```

その後、`wsl --install --distribution Ubuntu --no-launch`からやり直す

:::

## dockerを動かそう

### hello worldを実行してみる

初回のみ、

```powershell
wsl -d Ubuntu
exit
```

2回目以降は、下記のコマンドでWSLを開始する

```powershell
wsl -d Ubuntu
```

WSLを起動後、下記コマンドでユーザー、グループを確認できる

```bash
groups $(whoami)
```

以下のコマンドでdockerのコンテナを実行できる

```bash
# 初心者は、原因切り分けを容易にするためにpullとrunを分割したほうがいい
docker pull docker.io/library/hello-world
# docker実行
docker run docker.io/library/hello-world
```

<details><summary>想定出力</summary>

```
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:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
```

</details>

:::note warn
組織内プロキシによるアクセス制限がかかっている場合、systemdとdockerに別途設定が必要
設定を変更しなかった場合、docker.io(dockerhub)に接続できないため `docker pull`できない
:::

## 参考資料

### Microsoft公式：WSL2のインストール方法

https://learn.microsoft.com/ja-jp/windows/wsl/install

### docker公式：dockerのインストール方法

https://docs.docker.com/engine/install/ubuntu/

### cloud-init公式：WSL チュートリアル

https://cloudinit.readthedocs.io/en/latest/tutorial/wsl.html#create-our-user-data

### cloud-init公式：cloud-init による自動セットアップ

https://documentation.ubuntu.com/wsl/en/latest/tutorials/cloud-init/

### ubuntu公式：cloud-init による自動セットアップ

https://documentation.ubuntu.com/wsl/en/latest/tutorials/cloud-init/

### qiita:Docker DesktopなしのDocker環境をWSL2とcloud-initで構築する

https://qiita.com/yo-yamada/items/ed44bc72260ad5787d84#cloud-init%E3%81%AE%E6%BA%96%E5%82%99%E3%81%A8%E5%AE%9F%E8%A1%8C

### Debian 12 Cloud Init Docker Server

https://blog.programster.org/debian-12-cloud-init-docker-server

## 補足：過去のインストール手順と比較した改善ポイント

前バージョンの手順と比較すると、下記の差異がある。

https://qiita.com/KO_YAmajun/items/41ea85d30f143b25135c

:::note
- 手順の短縮
  - `cloud-init`により作業ステップを短縮
- Ubuntu24.04時点で自明となった手順を削除
  - systemdの有効化について
  - gpgのascii形式に関する説明
:::

[^1]: [Microsoft公式：WSL2のインストール方法](https://learn.microsoft.com/ja-jp/windows/wsl/install)

[^2]: [docker公式：dockerのインストール方法](https://docs.docker.com/engine/install/ubuntu/)