前提
特にVSCodeのRemote Containers使ってる人には耳寄りです。別に使ってなくてもMacでDocker Desktop使ってる人ならあてはまります。
あと、このポストはMacといってもM1 MaxなMacBook Proで確認したものです。なので同じMacでもIntel Macとかだと違う結果になるかもしれません。
また、ここで紹介しているものはまだExperimental(試験的)な機能なので不具合や問題を引き起こす可能性があります。なので試す方はその辺は承知の上で試してみてください。
はじめに
さて、MacでDocker Desktopというと「遅い」というのがこれまでの常識。自分のように普段VSCodeのRemote Containersで開発している人にとってはこの遅さはなかなかストレスフルなんだけど、Remote Containersの利便性も捨てられず自分の場合は我慢しつつ使っていた。
以前にこのあたりを改善すべくNamed Volumeを使うって話を書いたのだが、そこにも書いたようにこの遅さはCPUとかメモリとかの前にMacのファイルシステムとDockerとのいわば相性のようなものである。
このブログで紹介したように一部の大量に更新が入るファイル群が保管される領域をNamed Volumeにするだけでも大幅な効果はあるものの、それでも遅い。
自分の場合はTypeScript/ReactとPythonで開発することが多いんだけどTypeScriptでNext.jsを使ったアプリケーションだとyarn install
はもちろん、yarn dev
で開発サーバを起動しての処理もめちゃめちゃ重い。起動するのも時間がかかる上に開発サーバだと初回リクエストのたびにコンパイルが走るんだけどそれがまためちゃめちゃ遅い。
これはM1 Macでも健在で、自分のようにM1 Maxで10コアCPU、32コアGPU、16コアNeural Engine搭載で64GBのメモリを積んでいようが体感では大きく変わらない。なお、以前のブログを書いたときの環境は2019年のMBPでi9 2.3GHzの8コア、32GBメモリというスペックだった。これもスペック的にはそこそこだがコンテナについては控えめに見ても遅かった。
というわけでこの点に関しては諦めつつ過ごしていたのだが、そんなときに朗報が舞い込む。
Docker Desktopのアップデート通知が来ていたので何気なく見たところ virtiofs
をexperimentalでサポートするとあるじゃないか。
virtiofsさっそく試す
virtiofsってのはめっちゃ雑に説明するとホストOSとゲストVMとの間でいい感じに共有してくれる比較的新しいファイルシステムだそうで、MacOSの12から搭載されるという話は小耳に挟んでいた。で、これがDockerで利用すると遅い問題が一気に解決するらしいって話も聞いてはいた。
virtiofs - shared file system for virtual machines
その、virtiofsサポートが新たにリリースされたDocker Desktop 4.6.1で試験的にとはいえ使えるようになるということなのだ。これは試すしかない。というわけでこれを試すには、Dockerのアップデートも必要だがMacOSも12.2以降へアップデートが必要なのである。
早速、MacOSを12.3にアップデートし、Docker Desktopも4.6.1にした。あとはDocker Desktopの設定でvirtiofsを使うように設定するだけだ。
設定したら、VSCodeからプロジェクトを開く。なんとなくコンテナをリビルドしてみる。
実際に動かしてみると体感的にはとても速くなっている感じだ。特に問題になりがちだったyarn install
、yarn build
そしてNext.jsなどでの開発サーバの起動と実行(yarn dev
)を試したみたがそのどれもが体感的に速い。とても速くなった(気がする)。
ついでにPythonのプロジェクトでも確認してみる。自分の場合、Pythonのプロジェクトではscikit-learnなどの科学計算系のライブラリがM1をサポートしていないこともあり、プラットフォームとしてlinux/amd64
を指定してイメージをビルドし実行している。なのでより遅い状況だった。
だが、これも体感で申し訳ないが確実に速くなっている(気がする)。poetry install
はもちろん開発サーバの起動と実行も試してみたが速い。
もうちょっとちゃんと計測してみる
ここまで来たらせっかくなのでもう少しちゃんと測ってみよう。ということで以下を実行した結果を計測してみた。
npx create-next-app --ts next-app cd next-app yarn build
yarn build
を実行するとかかった時間がターミナル上で表示される。まず、試しにやってみた感じでは10.29秒とだいぶ速くなっている。前に計測したときの値は具体的には覚えていないが当時この辺りの会話してた人がWSL2で15秒くらいでMacと比べて速いねってDMが残ってたので20秒から30秒くらいはかかっていたはずだ。もしかしたらもっとだったかもしれない。
そして、前回のブログでも計測したyarn install
の時間を同様に試してみる。本当は同じマシンで前後の比較をするのがベストなんだけど簡易的にこのままテストしてしまう。比較対象は前回のブログでの計測結果だ。ただし、実際にはpackage.json
の中身は少し違う。具体的には一部のライブラリは新しいバージョンになっているのと、devDependencies
に以前はなかったライブラリが増えている。
やり方は同じように毎回node_modules
とyarn.lock
を削除してyarn install
を実行するだけだ。今回は3回の平均を取ってみた。
前回のブログではNamed Volume未使用で平均72.86秒(遅い!)、Named Volumeを使っても平均30.36秒だった。
翻って今回の実測値だが、Named Volumeなしで平均22.6秒とかなり満足の行くものだった。
22.6秒という数値そのもの、絶対値としては遅い・速いという意見は人によってあると思われるが、少なくとも自分の環境においてはこれまでと比べて大幅な性能向上が見られた。
Named Volumeを試してみる
前回、大幅な性能改善が見られたNamed Volumeも試してみる。同じくnode_modules
以下をNamed Volumeにして計測する。
あまり変わらないかなーと思ってたのだが、なんと平均で12.28秒という結果が出た。
Macでこれは元が遅かっただけに爆速になった感覚がある。
まとめ
というわけで結論としては、
M1 Mac使ってる人は今すぐ12.2以降にアップデートした上で、Docker Desktopを4.6.1にしてvirtiofsを有効にするんだ!
ただし、自分もまだちょっと使っただけだし、そもそもexperimentalな機能なので何があるかはわからないのはご承知おきを。日本人の大好きな言葉、自己責任でお願いします。
そもそも計測を同一マシンで有効化前後でしていないので比較はあくまで参考に。
追記(超重要)
上記の流れでVirtioFSとRemote Containersを使っていたのだが一点だけ問題が発生している。
それはRemote Containers上でgit commit
をしようとすると今の所確実に失敗するということだ。実際にはfatal: loose object a277d13df12e29299e51f51d77bf27b7a9cd9073 (stored in .git/objects/a2/77d13df12e29299e51f51d77bf27b7a9cd9073) is corrupt
というメッセージが出る。ハッシュの値はそのときによって違う。
一般的にこのメッセージが出たときの対応もしてみたが解消しない。Remote Containersの環境で発生はしているが試しにコンテナにdocker exec -it
で接続してgit commit
を実行しても同じ事象なのでRemote Containersは関係ない気もしている。
そしてこの問題はDocker desktop for MacでVirtioFSを無効にすれば解消する。ということでVirtioFSが何らかの問題を引き起こしているのは確実だと思う。ただし、このGitの問題以外では1ヶ月以上毎日のように使っていて特に問題は発生していない。
ワークアラウンドとして、このGitの問題は今の所 git add
とgit commit
をホスト側ですることで問題ない。それよりも普段の使い勝手のほうが僕的には体験がいいので今の所まだVirtioFSを使い続けている。
追記2
親切な方にTwitterで教えてもらった。ここのコメントに書かれている。
ということでこれはVirtioFSとMacの問題のようだ。
そしてその後のコメントにmacOS 12.4 betaでfixされているとあるので解決するのは時間の問題のようだ。
[Docker Desktop] Improve Mac File system performance · Issue #7 · docker/roadmap · GitHub