WSL2 で docker-compose を使いたい

※ 公式は `docker-compose` ではなく `docker compose` (Compose V2) を使用する事を推奨していますが、この記事のタイトルでは検索性や文脈を考慮して `docker-compose` と表記しています。


- まず初めに WSL2 がインストールされている必要がある
- ディストリビューションによって方法が異なるが、ここでは Ubuntu を前提とする

WSL で Docker を使う方法は定番でもいくつかあり、方法によって決定的に違う部分もある。

1. Docker の apt リポジトリを追加し、apt でインストールする方法
2. Docker 公式が提供しているインストールスクリプトを使用する方法
3. Docker Desktop を使用し、その中に含まれるものを使う方法
4. Rancher Desktop を使用し、その中に含まれるものを使う方法
5. それ以外の方法 (手動でのバイナリ配置など)

特に Docker Desktop for Windows の場合と Rancher Desktop の場合の裏側の仕組みは実質的な内容が他と大きく違う事になるので
想定している使い方に応じたインストール方法を選ぶ必要がある。
(この時、自分にとってどれが適切かわからない場合は上記の選択肢と共に AI に相談するといいと思います。)

ここでは、**Docker 公式の apt リポジトリを追加する方法** でインストールを行う。

## 事前準備

まずパッケージを最新化しておく:

もしまだ sudo apt-get upgrade していなかった場合は sudo apt-get update 後に実行してシステム全体を更新する事をお勧めします。
この部分の意味がわからない場合は、Debian 系ディストリビューションを使う上で必須の超前提知識なので恥ずかしがらずに検索するか AI に聞いてみて下さい。
生まれた時から知っている人は誰もいないので安心して調べましょう。(私も大昔に買った Debian 完全攻略的な、ちっこい本で知りました)

```bash
sudo apt-get update
```

## リポジトリ追加に必要なパッケージを導入し、鍵を配置
```bash
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
```

## APT リポジトリを追加

```bash
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
```

## Docker 関連パッケージをインストール

```bash
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```
もしここで

```
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Package docker-ce is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source

E: Package 'docker-ce' has no installation candidate
E: Unable to locate package docker-ce-cli
E: Unable to locate package containerd.io
E: Couldn't find any package by glob 'containerd.io'
E: Couldn't find any package by regex 'containerd.io'
E: Unable to locate package docker-buildx-plugin
E: Unable to locate package docker-compose-plugin
```

こんなエラーになる場合は [競合するパッケージがあるらしい](https://qiita.com/rin_aya6/items/d8c9b0808b56e5cb373d) ので削除する。

```
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done
sudo apt-get update
```

解消したかと思ったら次はこんなエラーが出た人はどいつだい? あたしだよ!!
```
W: GPG error: https://download.docker.com/linux/ubuntu jammy InRelease: The following signatures cou
ldn't be verified because the public key is not available: NO_PUBKEY 7EA0A9C3F273FCD8
E: The repository 'https://download.docker.com/linux/ubuntu jammy InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.
```
これはさっきの `/etc/apt/keyrings/docker.gpg` の作成が正しく行えていない場合に出る。
また、WSL2 が使えていなくて WSL1 を使っている状態の時も、ここでエラーになるという情報があったので、該当するかどうかを確認して欲しい (自分の場合は指定が間違っていたのだけど、この手順では上手くいったほうを載せてるので安心してほしい)

## インストール確認
冒頭にも書いた通り, `docker compose` と記載していますが, 現在ではまだ `docker-compose` コマンドも互換性の為にインストールされている可能性が高いです。

```bash
docker --version
docker compose version
sudo docker run hello-world
sudo docker ps -a
```

## sudo なしで Docker を使う
WSL2 環境では docker グループは既に存在している可能性が高いため、groupadd docker は通常不要です。

自分のユーザーを docker グループに追加：
```bash
sudo usermod -aG docker ${USER}
```

グループへの変更を即座に反映させるには、ログアウト後に再ログインするか、次のコマンドを実行します:
```bash
exec su -l ${USER}
```
グループへの追加が上手くいっていたら先ほどの docker run などは sudo なしでも動くはず
```
docker run hello-world
docker ps -a
```

## Docker デーモンの起動と自動起動設定
Docker Desktop for Windows を利用している場合、WSL2 からは Windows 側の Docker デーモンに接続するのが一般的です。この場合、WSL 内部で systemctl start docker 等を行う必要はありません。
そうではない場合は systemd を動かして自動起動を設定します。

`/etc/wsl.conf` に記載を追加する。

```bash
[boot]
systemd=true
```

書き込んだ後, WSL 自体を再起動する必要があります。

```cmd.exe
> wsl.exe --shutdown
```

再起動後には systemctl が使えるようになっているはずですが、WSL が古いとこの方法では上手くいかない可能性があります。

もし systemd が有効化できない場合には毎回手動で起動する方法もありますが、長期的に使うのには不向きです。(軽く試すのにはよいと思います)

```
sudo nohup dockerd > /dev/null 2>&1 &
```

あるいは [Colima](https://github.com/abiosoft/colima) という Docker Desktop の代替ツールを使う事で Docker CLI を通して使用する (現在の WSL ディストリビューション側では Docker デーモンを起動する必要がなくなる) 等の代替手段があるようです。
Colima は Homebrew でインストールできるようです (brew install colima docker docker-compose)。

systemd が有効化でき, systemctl が使える状態になっているかどうかは以下のコマンドの出力で確認できます
```bash
ps -p 1 -o comm=
```
この結果が `systemd` なら上手くいっています。
`init` なら伝統的な init が有効なので chkconfig 等で自動起動が設定できる可能性があります。
`bash` なら .bashrc で多重起動にならないように気を付けながら裏で dockerd 走らせるとかでいけるのかな? (どう考えてもいばらの道なので未確認)

systemd が有効な場合は以下のコマンドで起動できるはずです:
```bash
sudo systemctl start docker
```

ブート時に自動起動させる
```bash
sudo systemctl enable docker
```

自動起動するようになっているかどうかを確認する
```bash
systemctl is-enabled docker
```
enabled になっていれば自動起動するはず。