🫙

Docker Desktopって何のために入れるの?他に代わりはいないの?という話

に公開

前提

基本、Macユーザー向けの話です。

Docker Desktop (のGUI) いらなくない?

ぶっちゃけDocker Desktopいらなくないですか?

いや別にあって困るものではないのですが、個人的にはダッシュボードも滅多に開かないのでGUIはいらないと思っています。そして何と言ってもDocker Desktopのライセンスは一定規模以上の企業では有料です。ミニマムでも一人当たり月額$11もします。
今はまだ会社が無料で使える規模だからいいのですが、今後のためにDocker Desktopなしで扱えたほうがなにかと便利だろうと思います。

また、Docker DesktopはGUIを積んでいるせいで重いという話も聞きますし、であればもっとミニマムなツールに乗り換えたいでしょ、というのがきっかけです。

そもそもなんでDocker Desktopがいるの?

MacでDockerを使う場合はDocker Desktopを入れるのが一般的かと思います。でもLinuxではその必要はありません。なぜかというと、DockerはLinuxカーネルの仕組みを使って動作するアプリケーションだからです。
我々が普段使う docker コマンドはDocker CLIと呼ばれ、これはDockerデーモン (dockerd) とREST APIで通信を行うためのコマンドです。そしてこの dockerd (厳密には、より低レベルなランタイムである runc ) がLinuxカーネルの機能を使っており、例えばDockerコンテナは、 runcnamespace を使ってLinux上の名前空間を分離することによって構築されています。


出展 : コンテナはどのようにして作られるのか #Docker - Qiita

つまりMacOS にはこれらの dockerd, containerd, runc を動作させるための前提条件が揃っていない、ということです。よって別途Linuxの仮想マシンを用意しなければなりません。Docker Desktop は docker コマンドやGUIとともにこの仮想マシンを提供するアプリケーションだったというわけです。
Docker Desktopはその仮想マシン内で dockerd を起動することによって、Macやその他非LinuxOSで docker コマンドを使えるようにしています。

ここまで理解すると、Docker Desktopの本体はGUIではなく、それに同梱されたLinuxKitだと言っても過言ではないように思えてきます。

Docker Desktop の中心には、Docker が管理する軽量の LinuxKit VM があります。
Dockerデスクトップの舞台裏の魔法 | Docker

つまり、Linux仮想マシンさえ用意すれば

Docker Desktop を使わなくても良い、ということです。

ここで登場するのが Lima です。
https://github.com/lima-vm/lima

LimaはLinux仮想マシンを立ち上げ、ファイルマウント・ポートフォワーディングなどを自動的に行なってくれるツールです。簡単に言うとWindows以外で使えるWSL2です。
もともとLimaはMacで containerd を使うために開発されたツールですが、そこから派生して現在ではDockerやKubernetes用のランタイムとして使ったり、Mac以外のOSでも使えるようになったりしています。
またLimaは、Linux Foundationがクラウド普及のために設立したCloud Native Computing Foundation (CNCF) のSandboxプロジェクトとなっています。実際にRancher Desktop, ColimaなどのDocker Desktop alternative なツールのバックエンドとしても使われていることから、将来性も見込めるプロジェクトと見ていいでしょう。

Limaの使い方

LimaのインストールにはHomebrewを使うのが楽です。

$ brew install lima

Docker CLIをインストールしていない場合は合わせてインストールしておきましょう。私はDocker Desktopをインストール済みだったので必要ありませんでした。

$ brew install docker

LimaはYAMLで設定を記述するのですが、 dockerd を使用するためのテンプレートが同梱されているので、一旦それを使います。

$ limactl start template://docker

Lima内部で起動した dockerd に接続するためのUNIXドメインソケットの設定をしましょう。

$ export DOCKER_HOST=$(limactl list docker --format 'unix://{{.Dir}}/sock/docker.sock')

DOCKER_HOST の中身が unix:///Users/xxx/.lima/docker/sock/docker.sock のようになっていればOKです。
docker コマンドが使えるかどうかを確認しましょう。

$ docker run --rm hello-world

Hello from Docker! と出力されればOKです。

実際に使える?

Docker Desktopで開発していたプロジェクトでランタイムをLimaに切り替えて docker compose up したところ、以下のようなエラーが発生しました。

Error: EROFS: read-only file system, unlink '/app/index.html'
frontend-1  |     at unlinkSync (node:fs:1886:11)
frontend-1  |     at mayCopyFile (node:internal/fs/cp/cp-sync:206:5)
frontend-1  |     at onFile (node:internal/fs/cp/cp-sync:201:10)
frontend-1  |     at getStats (node:internal/fs/cp/cp-sync:170:12)
frontend-1  |     at checkParentDir (node:internal/fs/cp/cp-sync:150:10)
frontend-1  |     at cpSyncFn (node:internal/fs/cp/cp-sync:61:10)
frontend-1  |     at Object.cpSync (node:fs:3077:3)
frontend-1  |     at /app/src/scripts/prestart.mjs:97:6
frontend-1  |     at ViteNodeRunner.runModule (file:///app/node_modules/vite-node/dist/client.mjs:401:5)
frontend-1  |     at ViteNodeRunner.directRequest (file:///app/node_modules/vite-node/dist/client.mjs:381:5) {
frontend-1  |   errno: -30,
frontend-1  |   code: 'EROFS',
frontend-1  |   syscall: 'unlink',
frontend-1  |   path: '/app/index.html'
frontend-1  | }

このアプリケーションはVite + Reactで開発しているのですが、マルチテナント対応のため yarn dev のprescriptとして静的ファイルの置き換えを行っています。よってファイルの書き換えが発生するわけですが、LimaのDockerテンプレートはホストマシンのホームディレクトリを丸ごと仮想マシンの /Users/xxx にread-onlyなディレクトリとしてマウントしています。よってファイルの書き込みができなかったというわけです。

実際に仮想マシン内で /etc/fstab を確認してみると、 /Users/xxxro (read-only) になっていることがわかります。

$ limactl shell docker cat /etc/fstab

LABEL=cloudimg-rootfs   /        ext4   discard,commit=30,errors=remount-ro     0 1
LABEL=BOOT      /boot   ext4    defaults        0 2
LABEL=UEFI      /boot/efi       vfat    umask=0077      0 1
mount0  /Users/xxx      virtiofs        ro,nofail,comment=cloudconfig   0       0     <-- /Users/xxx が ro (read-only) になっている
mount1  /tmp/lima       virtiofs        rw,nofail,comment=cloudconfig   0       0

私の場合、Gitリポジトリは ~/src に格納しているので、ここをwritableとすることにします。よって、~/.lima/docker/lima.yaml を以下のように書き換えました。mount の設定はYAMLの一番下あたりにあるはずです。

...
mounts:
- location: "~"

- location: "{{.GlobalTempDir}}/lima"
  mountPoint: /tmp/lima
  writable: true

# Gitリポジトリ用のディレクトリははwritableにする
- location: "~/src"
  writable: true

これにより /Users/xxx/src に書き込みができるようになりました。

$ limactl shell docker cat /etc/fstab

LABEL=cloudimg-rootfs   /        ext4   discard,commit=30,errors=remount-ro     0 1
LABEL=BOOT      /boot   ext4    defaults        0 2
LABEL=UEFI      /boot/efi       vfat    umask=0077      0 1
mount0  /Users/xxx      virtiofs        ro,nofail,comment=cloudconfig   0       0
mount1  /tmp/lima       virtiofs        rw,nofail,comment=cloudconfig   0       0
mount2  /Users/xxx/src  virtiofs        rw,nofail,comment=cloudconfig   0       0   <-- /Users/xxx/src が rw (read-write) になっている

この設定で既存プロジェクトの docker compose も問題なく動作するようになりました。

まとめ

Docker Desktopって絶対必要なの?って話でした。結論としては、Macにおいては必要だけどそれがDocker Desktopである必要はないということですね。というわけでしばらくはDocker Desktopも残しつつ、Limaで問題がなさそうなら完全に乗り換えようかと思います。

ちなみに、Limaに乗り換えて目に見えるほど速度が速くなったかというと、そこまでの実感はありません。なんとなく速くなった気はします。ただ個人的には速度よりもバッテリーの消費が抑えられれば非常にありがたいと思っています。「最大16時間のワイヤレスインターネット」??嘘だろ?って勢いでバッテリーが減っていくので。

また、Colimaというdockerに特化したLimaのwrapperもあるのですが、以下の理由から採用を見送りました。

  • これを書いている時点で半年近くreleaseが更新されていない (新しい物好きなのでLimaの最新のリリースを使いたい)
  • よりレイヤーの低いLimaを使うことで理解を深めたい
  • Limaを使ったとしてもそんなに手順が煩雑になるわけではない

ただ開発が止まっているわけではなさそうですし、Docker用途であればColimaの方が間違いなく手軽なので、そちらを使っても全然いいと思います。Star数もこちらの方が多いですし。
https://github.com/abiosoft/colima

参考資料

https://qiita.com/Taka_input/items/e5a9f02d6ce9223b11dc
https://www.docker.com/ja-jp/blog/the-magic-behind-the-scenes-of-docker-desktop/
https://qiita.com/mykysyk@github/items/26926aa98c1591b2f1ed
https://docs.docker.jp/v1.11/engine/understanding-docker.html#id7

Discussion