devcontainers on Finch は可能 ？

[Supershipグループ Advent Calendar 2022](https://qiita.com/advent-calendar/2022/supership)の10日目の記事を22年入社、新卒１年目の永井雄也が担当します。

# はじめに

先日、AWSからDocker Desktopの代替である [Finch](https://github.com/finagle/finch) が発表されました。Docker Desktopの商用利用の料金が上がり続けている中、代替足りえるのか注目している方もいらっしゃるでしょう。とはいえ、数年前ならいざ知らず、今のコンテナ開発はdockerを中心にエコシステムが築かれています。例えば、コンテナ開発を快適にしてくれるVSCodeのdevcontainersが挙げられます。個人的には、devcontainersも一緒に使えないとコンテナ開発をする気が起きないくらいdevcontainersを気に入っております。devcontainersが使えるまでは手元の開発でFinchを利用したくないなと思っています。逆にいえば、devcontainersが使えればFinchでもいいため、devcontainers on Finchが可能か否か調べました。本記事ではその結果を記します。

結論、Finch v0.1.0では、devcontainers実行時の初っ端のバージョン判定でエラーが起こり、devcontainers on Finchは不可能でした :cry:
今後のサポートに期待したいですね。

# 仮説

Finchのユーザーに提供されるCLIはdockerと異なりますが、FinchのCLIはdocker互換です。公式によると、FinchのCLIは[nerdctl](https://github.com/containerd/nerdctl)ベースで開発されているそうです。nerdctlはdockerとは別のコンテナを操作するエンドユーザー向けのCLIです。nerdctlはdocker互換を保つように開発されているそうです。つまり、nerdctlベースのFinchもdocker互換が保たれていると考えられます。

今回の検証では、VSCode devcontainersのdockerとdocker composeのパスのコンフィグをFinchに変えるだけでdevcontainer on Finchを実現できると仮説を立てました。devcontainersはコンフィグのDocker PathとDocker Compose Pathに指定されたCLIを介してコンテナを操作します。両設定をFinchとFinch composeにしてあげれば、devcontainersがFinchを介した操作を行なってくれます。FinchのCLIはdocker互換であるため、これだけでdevcontainers on Finchが実現する可能性があります。

# 仮説検証

## 1. 必要なソフトウェアをインストール
前準備として、以下３つのソフトウェアをインストールします。Finch v0.1.0ではmac版しかリリースされていないため、macでしか検証できません。ご注意ください。
+ VSCode
+ VSCode Extensionsのdevcontainers
+ Finch (https://github.com/runfinch/finch)

## 2. devcontainersのdockerとdocker composeのpathをfinchに差し替え
devcontainersにFinchを呼び出してもらうために、devcontainersのdockerとdocker-composeのpathをFinchに差し替えます。

今回はユーザーのsettings.jsonに以下の内容を追記しました。
```settings.json
{
    "dev.containers.dockerComposePath": "finch compose",
    "dev.containers.dockerPath": "finch"
}
```
※1 VSCodeの設定同期を有効にしていると、今回の変更が他のPCの設定に同期されてしまうため、検証が終わったら忘れずに設定を元に戻しましょう。
※2 上記２つの設定は、ユーザーのコンフィグにしか設定できないため、ご注意ください。

## 3. 適当なdevcontainers環境を用意し、Open Folder in Containerを実行
Open Folder in Containerが実行でき、かつ、よく使うポートの解放やマウント、devcontainersの〜Command系が実行される適当なdevcontainersの環境を用意します。

今回は下記のdevcontainers環境を用意し、`.devcontainer` を選択し、Open Folder in Containerを実行しました。

```
ディレクトリ構成

└── .devcontainer
    ├── .devcontainer.json
    ├── Dockerfile
    ├── docker-compose.yml
    └── post_create_command.sh
```

```.devcontainer.json
{
    "name": "devcontainer test on finch",
    "workspaceFolder": "/root",
    "dockerComposeFile": [
        "./docker-compose.yml"
    ],
    "service": "dev",
    "postCreateCommand": [
        "bash",
        ".devcontainer/post_create_command.sh"
    ]
}
```

```Dockerfile
FROM ruby:latest

RUN apt-get update \
	&& apt-get install -y --no-install-recommends \
		postgresql-client \
	&& rm -rf /var/lib/apt/lists/* \
    && gem install rails
```

```docker-compose.yml
version: "3"
services:
  dev:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 9080:9080
    volumes:
      - ../:/root/src
```

```post_create_command.sh
echo "test"
```

# 結果
Open Folder in Container実行時、docker versionの判定でつまづき、devcontainers on Finchは不可能でした。実行時のログを下記に示します。Open Folder in Containerを実行時、初めにdockerのバージョン判定で `docker version --format {{.Server.APIVersion}}`が実行されます。そもそもfinchのversionのサブコマンドでは `--format {{.Server.APIVersion}}` がサポートされていないため、エラー発生でOpen Folder in Containerが失敗しました。Finch versionはFinchのバージョンを出力するため、`--format {{.Server.APIVersion}}`がサポートされていたとしても、エラーになっていたでしょう。初っ端のdocker versionの判定でつまづき、devcontainers on Finchは不可能でした。

```
# Open Folder in Containerの実行時ログ
[877721 ms] Dev Containers 0.262.3 in VS Code 1.73.1 (6261075646f055b99068d3688932416f2346dd3b).
[877720 ms] Start: Run: finch version --format {{.Server.APIVersion}}
[877728 ms] time="2022-11-29T17:31:15+09:00" level=fatal msg="unknown flag: --format"
```

# 考察

バージョンの判定を超えたとしても、devcontainers on Finchは厳しそうです。今回の検証では初っ端のバージョン判定でエラーで終わってしまいました。バージョンの判定くらいなら`finch version --format {{.Server.APIVersion}}`が呼ばれたら、devcontainersが許容する適当なdockerのバージョンを出力するようにコードを改変すれば先に進めます。ただ、バージョン判定さえ超えられれば、うまくいくかと言われると怪しいです。devcontainersの実装を調査したわけではないですが、devcontainersはバージョン判定の他にもdockerの出力依存していそうです。実際、nerdctl系がdocker互換と言っても出力含め差異は多そうで、devcontainersでnerdctlをサポートしてほしいという[PR](https://github.com/microsoft/vscode-remote-release/issues/6014)が１年以上経ってもcloseしていません。バージョン判定を超えたとしても、devcontainers on Finchは実現できなさそうです。

# 最後に

残念ながら、Finchではdevcontainers on Finchが不可能でした。無料は魅力ですが、devcontainers on Finchの実現、または、Finch関連でdevcontainersを凌駕する何かが実現するまで私が手元の開発でFinchを使う機会はなさそうです。これからFinchがdevcontainersを含めdocker周りのエコシステムにどれだけ追従するかは定かではありませんが、FinchがAWSを活用した開発の一便利ツールで終わってしまわないことを祈るばかりです。

## 余談
あまり目立ってないですが、Finch以外にも商利用無料なDocker Desktopの代替が存在します。[Rancher Desktop](https://rancherdesktop.io/)です。Rancher Desktopの場合、dockerコマンドをそのまま使えるため、devcontainers on Rancher Desktopが可能だったりします。

それと宣伝ですが、Supershipではプロダクト開発やサービス開発に関わる人を絶賛募集しております。
ご興味がある方は　[Supershipグループ 採用サイト](https://supership.jp/recruit/)　よりご確認ください。是非ともよろしくお願いします。