Docker Desktop for Mac から Docker on Lima に乗り換える

# この記事を見ると嬉しい人
下記を満たす人が見ると嬉しいであろう記事です。
どこかが欠ける人はヒントにはなるかもしれませんが、他により良い記事があるかもしれません。

* MacでDockerを使いたい
* Docker Desktop for Macを使っている
    * 有料になるから回避したい
    * Docker Hubは無くていい
    * 構築済みイメージは一度消えても良い
* I/O含め速度至上主義とまでは考えていない
* Intel Macを使っている（M1で同じ手順が通じるかは確認していません）
* OSはMonterey　12.1(他のバージョンは未確認)
* ターミナルを触ることにアレルギーがない

# やること
Docker Desktop for Macをアンインストールし、LimaでDocker Engineを起動します。
ホスト側（mac）からUNIXドメインソケットを使ってLima上のDocker　Engineにアクセスします。
この方法であれば、Docker Desktopを使っていたときとほぼ同じ感覚でDockerを利用しつづけることができます。

# ざっくり手順
1. Docker Desktop for Macのアンインストール
2. Lima、Docker CLIのインストール
3. Docker Composeのインストール
4. Lima用イメージの作成
5. 動作確認

# 詳細手順
## Docker Desktop for Macのアンインストール
1. Docker メニューから Troubleshoot を選んで Uninstall を選択
2. [Docker Uninstall shell](https://github.com/docker-archive/toolbox/blob/master/osx/uninstall.sh)をローカルに保存し、rootで実行

## Lima、Docker CLIのインストール
Homebrewでちゃちゃっとインストールします。

```shell
brew install lima docker
```

この時、
> Error: python@3.9: the bottle needs the Apple Command Line Tools to be installed.
  You can install them, if desired, with:
    xcode-select --install

な感じでエラーになって止まってしまう場合は、書いてあるとおり

```shell
xcode-select --install
```

してxcode commandline toolsをインストールしてから再実行します。
よしこれで。。。と思ったところでさらに

> Error: Permission denied @ apply2files - 

みたいなエラーで止まってしまう場合は見たまま、権限のエラーなので解消してやります。

```shell
sudo chown -R $(whoami) $(brew --prefix)/*
```

これで今度こそインストール完了。

## Docker Composeのインストール
せっかくなのでv2を使う。
[公式ドキュメント](https://github.com/docker/compose/tree/1a73d1412d562e32effbe7b322f17e8d77ad7755#where-to-get-docker-compose)を確認すると、どうやらmacはDocker Desktop使えばいいよと書いてます。
が、Docker Desktopはアンインストールしたんや。。。
ということで、その真下にあるLinuxの手順に則って手動インストールを行います。
Linux向けの手順としながらも、バイナリはちゃんとmac用も用意されているのでご安心を。
Intel macなのでx86_64のバイナリを使います。
バイナリのパスはこのままでも使えるとは思いますが、リリースページに添付されているものを参照してください。

```shell
mkdir ~/.docker/cli-plugins 
curl -SL https://github.com/docker/compose/releases/download/v2.2.3/docker-compose-darwin-x86_64  -o ~/.docker/cli-plugins/docker-compose
chmod +x ~/.docker/cli-plugins/docker-compose
```

ダウンロードが完了したら実行権限の付与をしておきます。
ここで一旦、コマンド使えるか確認しておきましょう。

```shell
docker compose version 
```

バージョンが表示されたら完了。

## Lima用イメージの作成
[公式サンプル]をベースにというかほぼそのまま使います。
それっぽいディレクトリを作って定義ファイルをダウンロードします。

```shell
mkdir ~/Lima
curl https://github.com/lima-vm/lima/blob/master/examples/docker.yaml > ~/Lima/docker.yml
```

ダウンロードした定義ファイルをエディタで開き、マウントの設定を変更します。
ホームディレクトリ「~」がマウントされるようになっていますが、書き込みができないので書き込みをできるようにしておきます。

```yml
mounts:
- location: "~"
  writable: true #これを足す
```

これでホームディレクトリがマウントされますが、シンボリックリンクは効かないのでLimaのインスタンスやDockerでアクセスするパスにシンボリックリンクが含まれる場合は、実パスを使うように気をつけましょう。
また、書き込み可能な状態でホームディレクトリをマウントするのはちょっと。。。という場合は影響範囲を絞ったディレクトリを作り、このディレクトリを追加でマウントするとよいです。
例えば

```shell
mkdir ~/Project
```

としてディレクトリを作っておき、

```yml
mounts:
- location: "~"
- location: "~/Project"
  writable: true
```

とすれば、ホームディレクトリは読み取りのみで、追加で`~/Project`が書込み可能な状態でマウントされます。
[公式サンプル]:https://github.com/lima-vm/lima/blob/master/examples/docker.yaml

設定が完了したのでLimaのインスタンスを立ち上げます。

```shell
cd ~/Lima
limactl start docker.yml
```

初回起動時はymlを指定してstartします。
起動シーケンスに入ると「設定どうする？」という感じの選択肢が提示されるので
`Proceed with the default configuration`
を選択します。

２回目以降はファイル名の拡張子除いた部分がインスタンス名になっているので

```
limactl start docker
```

で起動します。
停止の時などもこの名前を利用します。

起動した`docker`インスタンスのshellを利用するには

```shell
limactl shell docker
```

を叩きます。そんなに使うことがないにしても、若干面倒なので`lima`だけで使えるようにデフォルトインスタンスの設定をしておきます。

```shell
export LIMA_INSTANCE=docker
```

次に、ホスト側からLimaのDocker Engineにアクセスできるようにします。

```shell
export DOCKER_HOST=unix://$HOME/.lima/lima_docker/sock/docker.sock
```

ここまでの作業でDocker Desktopと同じ感覚でdockerが使えるようになりました。

### 使ってみる
とりあえずバージョンを見てみます。

```shell
docker version
```

無事バージョンが出力されました。
次に手元にある適当なdocker-compose.ymlを使って動かしてみます。

```shell
docker compose up -d
```

> error getting credentials - err: exec: "docker-credential-desktop": executable file not found in $PATH, out: ``

なんかエラーでました。
コンフィグのキーが変わっているようです。
参考：[Docker Community Forum](https://forums.docker.com/t/docker-credential-desktop-exe-executable-file-not-found-in-path-using-wsl2/100225/5)
ズバリ

> Solution:
In ~/.docker/config.json change credsStore to credStore

と書かれているので、ファイルを開いてキーを書き換えます。
そして再びupしてみます。

> Error response from daemon: pull access denied for **********, repository does not exist or may require 'docker login': denied: requested access to the resource is denied

またエラーがでました。
`docker login`で「ログインしておけよ」って言われています。
「適当な」docker-compose.ymlの中を確認すると、Docker Hubからイメージを取得していました。
この参照をやめてdocker-compose.ymlにはbuildコマンドを使ってDockerfileからイメージを作成するように記載しました。
今度こそupすると無事環境構築できていることが確認できました。

# おまけ
## Limaの操作
* 起動中のインスタンス一覧

```shell
limactl list
```

* 停止

```shell
limactl stop docker
```

* 削除

```shell
limactl delete docker
```


* VMのスペック調整

```shell
vi ~/Lima/docker.yml
```
cpus: 2
memory: "2GiB"
disk: "10GiB"
の感じで指定可能。

* ボリュームのマウントを変えたい：一旦Limaのイメージを削除してから作り直します。

```shell
limactl stop docker
limactl rm docker
vi ~/Lima/docker.yml
    ~設定変更~
limactl start ~/Lima/docker.yml
```

# 参考にさせてもらった記事

https://zenn.dev/matsukaz/articles/31bc31ff1c54b4

https://www.amane.to/archives/674