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コンテナは、 runc
が namespace
を使って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 です。
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/xxx
が ro
(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数もこちらの方が多いですし。
参考資料
Discussion