Mirrativ Tech Blog

株式会社ミラティブの開発者(バックエンド,iOS,Android,Unity,機械学習,インフラ, etc.)によるブログです

Docker + Mac どうする問題

Mirrativバックエンドのエンジニア @stakme です!

みなさんMacでDockerしてますか?今回は私から、Mac+Docker開発についての文章をお届けします。Docker Desktop for Macの有料化など、最近話題の多いところですよね。

ただし法的問題を含みますので、記事の正確性に配慮していますが、内容は保証しません。法的問題は弁護士に相談しましょう。

tl;dr

  • 大前提として「GUIを使わければMac版Docker Desktopは無料」ではない
  • Docker Desktop for Macは便利だが、マウント起因でパフォーマンスに影響を受けるケースも存在する
  • 「買わないなら、考慮すべき要素が多い」ことは文字数で伝わるはず

とりうる選択肢は3つあります。①Docker Desktopを適正に利用する、 ②Docker Desktopを利用せずに同等の開発環境を自力で構築する、③Macでの開発を実質やめる、この3つです。最終的に私は③を選択し、Linux VMで開発しています。(12/22 10:45 追記)

まずは現状認識

大事なことなので最初に書いておきたいのですが、「Docker Desktop for Mac のGUIを使わない会社はサブスク不要」ではありません。

Docker Desktop を無料で使えるのは、下記のケースのみです。

  • small businesses (fewer than 250 employees AND less than $10 million in annual revenue)
  • personal use
  • education
  • non-commercial open source projects.

www.docker.com

従業員が250人未満であり、なおかつ年間収益*1が1000万ドル未満の企業では、無料プランを選択できます。それ以外の企業では有料プラン(月5~21ドル)が必須であり、対応の猶予期限は2022年1月31日です。GUIを使うかどうかは一切関係ありません。

ではそのDocker Desktopとは何なのか。プラン毎にさまざまな機能が提供されていますが、個人的に特に嬉しいものをピックアップするならこんな感じですね。

  • Dockerクライアント
  • Linux + dockerd に近い体験
    • -v でMacのディレクトリをマウントできる
    • -p でローカルにポート公開できる
    • VMのメモリサイズやディスク容量を簡単に扱える

上記のうち、クライアントはDocker Desktopなしでインストールできます。他方、Macで動くdockerdは存在しません。クライアントだけでDocker開発を行うことはできませんので、dockerdを何らかの方法で調達する必要があります。

docs.docker.com

繰り返しますが「GUIを使わないからDocker Desktop for Macなしでも大丈夫」ではありません。Docker Desktop for Macを使わないのであれば、自力でdockerdの調達が必要です。

必要なのはdockerd

上述したように、DockerクライアントはDocker Desktopなしでもインストールできます。buildxやcomposeなどのプラグインも極めて容易にインストールすることができます。Docker Desktop for Macのインストーラーは便利ですが、かといって「クライアントを簡単にインストール・アップデートするために有料サブスクリプションを採用すべき」という程の手間ではないように思います。

また、Docker有料プランはレジストリや監査機能などのクラウドサービスを提供していますが、率直に言って利用したことがなく、現状で利用する予定もありません。個人的な興味はあるんですが… 利用しない以上、そこに対価を支払うことは正当化できません。

つまるところ、我々がほしいものはdockerdなのです。そして公式サポートのあるLinux環境であれば、VM上でdockerdを動かすのは簡単です。私は以前からDocker Desktopを使うことなく日々の開発を行なっていますし、場面によっては処理速度が向上したケースもあります(後述します)。

なーんだそれなら買う必要ないじゃん!終了!と思いますよね。ところがですよ

困りがちなポイント

Docker Desktop for Macと同等の環境を実現しようとして (12/22 10:45 追記) VM上にdockerdを構築するとき、主として3つの問題があります。Linux、バインドマウント、ポートフォワードです。

Lima

先に触れておくと、3つの問題を一気に解決するLimaという選択肢があります*2

github.com

このうちLima環境で利用できるnerdctl版composeコマンドは、docker-compose v2と部分的な互換性があるものの、欠けているコマンドもあります。開発において頻度高く使うものは揃っている一方、run, exec, port などの個人的によく使うサブコマンドがないのは悩みどころ。

ではLimaを使わない場合、どのような対応が必要なのか。ここから一つずつ見ていきます。

Linux

まずdockerdを動作させるためのLinuxマシンが必要です。これはMacローカルでVMを動作させるのが手軽でしょう。VMを用意する方法としてはVirtualBoxやQEMU直接操作なども試しましたが、multipassが手軽でよかったです。

multipass.run

Ubuntuにdockerdをインストールする方法はドキュメントが整備されているので、VMさえ準備してしまえば、その後の問題は少ないと思います。

docs.docker.com

バインドマウント

dockerコンテナにマウントできるのは、dockerdが動作するLinuxに存在するディレクトリです。あらかじめMacのディレクトリをLinuxマシンにマウント等しない限り、Macのローカルファイルをコンテナにマウントすることはできません。

ちょっと分かりにくいので、具体例を挙げます。Linux VMにdockerdを準備し、ssh経由でクライアントを繋いで、Macのターミナルから下記のコマンドを実行したとします。

DOCKER_HOST=ssh://some_docker_host docker -v /Users/stakme:/workdir run ubuntu 

このとき、コンテナにマウントされるのはMacの /Users/stakme ではなく、Linux VMの /Users/stakme です。ハチャメチャに分かりにくいです。

Docker Desktop for Macはこの問題を解決してくれます。-v /Users/stakme を指定するだけで、コンテナにMacの /Users/stakme をマウントしてくれるわけです。とても分かりやすいですね!

ただ、わかりやすい一方、マウントされたMacのディレクトリにはコンテナからのファイルアクセスが遅いという問題があります。一つの例として、マウントされたディレクトリにコンテナから書き込む処理*3を環境ごとに実行してみると、以下のようになります*4

マウントあり マウントなし
Docker Desktop 2.8 MB/s 374 MB/s
Linux VM (multipass) 348 MB/s 329 MB/s

multipassはLinux上のディレクトリをマウントしています。他方、Docker DesktopはMacのディレクトリをマウントしています。マウントされたMacディレクトリに対してコンテナがデータを書き込むとき、顕著なスピード差があると分かります。

ベンチマークの場面だけでなく、実際の開発作業への影響もあるようです。弊社のバックエンド開発においては、コンテナ上で「大量のファイル自動生成を行うmake」を実行するときに有意な差が生じます*5

real user sys
Docker Desktop (cached) 03m16.510s 08m40.403s 10m28.124s
Docker Desktop (delegated) 02m34.532s 06m41.766s 08m54.154s
Linux VM (cached) 01m1.189s 05m24.025s 03m23.608s

ちなみに筆者の環境においては、テスト実行時は有意な差が見受けられませんでした。ディスクIOの影響を受けにくいタスクでは差が出ないようです。そもそもコンテナ上で書き込まない(Macで実行するのが一番速い)というユースケースもあるでしょう。したがって「Docker Desktopをやめれば、全ての処理が必ず速くなる」とは言えませんが、ケースによってはコンテナ上での処理時間を短縮できるかもしれません。

ポートフォワード

コンテナのポートを公開する -p の意味するところは「dockerdのローカルホストに公開する」ということです。つまりVMからはローカルに見えるけれども、Macから見るとローカルに見つからないわけですね。

これは単純に「毎回Mac側で ssh -L する」だけで対応できるので、あまり大きな問題にはならないですが、地味にめんどくさいです。VSCode SSH Remoteのような支援機能が欲しくなるかもしれません。

f:id:stakme:20211203194224p:plain
VSCodeのポートフォワード支援は地味に助かる

結局どうするか

ここまで見てきたように、MacからVM上のdockerdを利用して開発をするには、考慮すべき多くの問題があります。Docker Desktop for Macは、この複雑性をいい感じに(場面によっては発生する一定の性能低下と引き換えに)覆い隠してくれていたのですね。

ただ、私個人の判断としては、単純なLinux VMを触る構成のほうが扱いやすく、ニーズにもあっていると感じています。業務ではmultipass + VSCode SSH Remoteでの開発をおこなっていますが、問題を感じることはありませんでした*6。現在はLinux VM上で gh repo clone し、そこですべての作業を完結させています。

Docker Desktopは親切で気が利いていてとっつきやすく、偉大です。ただその反面、弊社でいえば「コンテナ上でのmakeが遅い」という問題が生じたり、Mac/Linuxを行き来するスイッチングコストを感じてしまったり*7、「なんか原因不明でよくわかんないけど遅いケースがある… Docker Desktopのせいでは…?」と疑って調査して切り分ける必要があったりしました。あえてその状態で開発するよりは、Linux VMに寄せきってMacにファイルを置かないほうが(私の場合は)楽かなと感じています。

あと6週間

Docker Desktopを買うのか、無料枠で使うのか、利用せずに自前で環境構築するのか。どのような決定をするにしろ、猶予期間の終了は2022年1月です。このタイミングに起因する問題もあると思います。12月〜1月は時期的に検証コストを割けないとか、いまは対応できないから一旦継続したいと判断される場合もあるのではないでしょうか。

さらに中長期的には、開発用マシンをIntel搭載機からApple Silicon搭載機に切り替えていく必要があります。弊社の場合、まだM1搭載モデルを全面導入できていませんので*8、Docker Desktopの移行期限である1月末までに「全員でM1モデルに乗り換え、開発環境を検証・一新する」というような対応は相当困難な状況になっています。そのような時期的要因により「とりあえず全員M1に移行するまで現状維持しつつ、あらかたマシンが更新されてから開発環境について検証・検討する」という対応も直近ありえるかもしれません。

We are hiring!

この記事ではDocker Desktopになるべく話題を絞ったので、弊社バックエンドの具体的な開発スタイルやツールについてはあまり触れることができませんでした。そのような話題に興味のある方は、ぜひカジュアル面談でお尋ねください。

meety.net

コンテナをしばき倒すのが大好きな人類のみなさん!弊社の採用情報をぜひご確認ください!!! 🙏

www.mirrativ.co.jp

*1:売上、利息収入、賃料収入などを合わせたもの

*2:ただし私の手元の環境ではcomposeサブコマンドがなぜか動作させられず、検証できていません。そのため詳細な調査もなし

*3:docker run -v $PWD:/workdir --workdir /workdir --rm ubuntu:latest /bin/dd if=/dev/zero of=test bs=1k count=10000 同等のコマンド

*4:Intel版MacBook Pro (2019), Docker version 20.10.11, build dea9396, 試行回数それぞれ1回の参考値

*5:この場面では、マウントオプションcachedとdelegatedのいずれを選ぶかによって性能差がありそうな結果になりました。他方、ddをぐるぐる回すような簡易テストでは両者の差を確認できませんでした。ddによる計測はあくまで指標のひとつであり、単純なベンチマークの数値を絶対視できないことが分かります

*6:ただし「メモリ割り当てが足りずにトラブル発生」という場面が何度かあったため、現在は試行錯誤のコストを低減するために24GBのメモリを割り当てています

*7:地味ですがdateやpsのようなコマンドの使い方が違うとか、node_modulesの中身がプラットフォーム依存になっているとか、そういう物心両面のコスト

*8:技術的な制約ではなく、納期が長いため