こんにちは。今年の4月に入社したプラットフォーム技術部の杉森です。データ分析基盤の構築を行っております。
弊社のとあるアプリケーションの開発環境として Docker を使用しているのですが、 Apple シリコンの macOS での開発環境の立ち上げに多くの時間がかかっており、その問題を改善できないか調査したのでご紹介します。
問題
開発環境の立ち上げプロセスにおいて現在最も時間がかかっているのは webpack によるフロントエンドアプリケーションのビルドです。
Apple シリコン(M2 チップ)の macOS (以下「M2 マシン」という。)で Docker Desktop を使用し開発環境を立ち上げてみると、 webpack の初回ビルド時間は
Time: 674900ms
約11分かかりました。日が暮れてしまいます。
また、ファイル更新時のビルド時間は
Time: 26101ms
約26秒です。
毎度これほど待たなければならないので開発体験は良くありません。(最初は長くて絶望してましたが、次第に仏の心が芽生え M2 マシン君を応援できるようになりました。)
しかし私に仏の心が芽生えようとも、困っているのは私だけではないので、なんとかして改善をしようと思いました。
対象のアプリケーションは膨大な数のアセットファイルが存在するため時間がかかるのは想像できるものの、改善の余地はありそうです。ちなみに、このアプリケーションではあるディレクトリに JavaScript ファイルが合計20万行ほど存在し、膨大なアプリケーションです。
本記事では webpack のビルド時間に焦点を当て、ビルド時間を短くする ことを目標とします。
原因
これだけのビルド時間がかかっている原因の1つに考えられるのは Intel 向けのイメージを使用していることです。
Docker イメージのビルド時にオプションとして--platform linux/amd64
を指定することで Intel 向けのイメージをビルドしているのですが、 Docker Desktop では そのコンテナの実行時に QEMU によるエミュレーション環境が使用されます。
QEMU はクロスプラットフォーム仮想化エミュレータであり、さまざまなハードウェアアーキテクチャやプラットフォーム上でソフトウェアを実行できます。例えば M2 マシンの ARM64 アーキテクチャ上で AMD64 のプログラムを実行できます。QEMU はハードウェア全体のエミュレーションを行うためどうしても性能が低下してしまいます。
( ARM64 向けのイメージを使用するのが速度改善には最適なのですが、元々この開発環境が Intel チップで動いてきた環境であり、ARM64 向けに移植することが困難な事情があるため、本記事では前提条件としてご了承ください。)
解決策 “Rosetta 2 の使用”
エミュレーション環境において速度を向上させる一つの手段として、 Rosetta2 の活用が挙げられます。
Rosetta2 は、 Apple が提供するツールで、 Intel ベースのアプリケーションを Apple シリコンベースのマシンで実行するためのエミュレーションレイヤーです。 AMD64 バイナリを ARM64 向けに変換してくれます。QEMUは仮想的なハードウェアを作り出してプログラムを実行するのに対し、Rosetta2はプログラムそのものを最適化して実行するので、QEMU を使用するよりも高速であると考えられます。
ということで、Rosetta2 を使用して Apple シリコンのマシンで Intel コンテナを実行できるツールとして、 Docker Desktop と OrbStack の2つを試してみました。
Docker Desktop “Rosetta for Linux”
1つ目は2023年10月にリリースされた Docker Desktop 4.25 から利用できる “Rosetta for Linux” という機能です。この機能は今まではベータ版でしたが、ついに正式リリースされました。
以下 Rosetta for Linux の説明の抜粋です。
- Rosetta for Linux GA: Docker now supports running x86-64 (Intel) binaries on Apple silicon with Rosetta 2. It’s no longer an experimental feature but a seamlessly integrated component of Docker Desktop.
- Near-native emulation: The x86_64 emulation performance is now nearly on par with native execution, all thanks to Rosetta 2. This means you can expect near-native speed when running your applications.
訳:
- Rosetta for Linux GA : Docker は現在、 Rosetta2 を使って Apple シリコン上で x86-64(Intel)バイナリを実行することをサポートしています。これはもはや実験的な機能ではなく、 Docker Desktop にシームレスに統合されたコンポーネントです。
- ネイティブに近いエミュレーション: x86_64 エミュレーションのパフォーマンスは、 Rosetta 2 のおかげでネイティブ実行とほぼ同等になりました。つまり、アプリケーションの実行時にネイティブに近い速度を期待できます。
設定で Rosetta 2 を使用するというオプションが追加され Rosetta2 を使用したエミュレートができるようになったようです。
こちらを試したいと思います。
OrbStack
2つ目は Docker Desktop for Mac の代替ツールとして2023年9月に正式リリースされた、OrbStack です。
公式ページに以下説明がありました。
What is OrbStack?
OrbStack is a fast, light, and simple way to run containers and Linux machines on macOS. It's a supercharged alternative to Docker Desktop and WSL, all in one easy-to-use app.
訳: OrbStack は、macOS 上でコンテナと Linux マシンを高速、軽量、シンプルに実行する方法です。Docker DesktopとWSLに代わる、使いやすいアプリです。
Intel (x86) emulation
On Apple Silicon, OrbStack uses Rosetta to run images built for Intel CPUs (x86_64/amd64 architecture) seamlessly with good performance.
訳: Apple シリコン上では、 OrbStack は Rosetta を使ってIntel CPU(x86_64/amd64アーキテクチャ)用にビルドされたイメージをシームレスに実行し、良好なパフォーマンスを発揮します。
Docker Desktop よりも高速にコンテナを実行でき、 Apple シリコンでは Rosetta2 を使用してエミュレートしてくれるらしいです。
ちなみに Docker Desktop との比較をしたページがありました。相当自信がありそうです。(期待大)
試してみる
ということで試してみました。
Docker Desktop “Rosetta for Linux”
まずは Docker Desktop を試してみます。
Docker Desktop 4.25 から利用できる機能なので、バージョンアップデートをしておきます。
アップデートが完了したら Settings > General と遷移し、“Use Rosetta for x86/amd64 emulation on Apple Silicon” にチェックを入れて適用します。これで Rosetta を使用したエミュレートを行ってくれます。
そして開発環境を立ち上げてみるとwebpackの初回ビルド時間は
Time: 469741ms
でした。
ファイル更新時のビルド時間は
Time: 12638ms
となりました。
QEMU を使用していたときよりも速くなり、初回ビルド時間は30%、ファイル更新時のビルド時間は50%減少させることができました。
OrbStack
次にOrbStackを試してみます。
以下を参考に Apple シリコン向けの OrbStack をインストールします。
まずはコンテキストの切り替えを行います。
$ docker context list NAME DESCRIPTION DOCKER ENDPOINT ERROR default Current DOCKER_HOST based configuration unix:///var/run/docker.sock desktop-linux * Docker Desktop unix:///Users/sugimori/.docker/run/docker.sock orbstack OrbStack unix:///Users/sugimori/.orbstack/run/docker.sock $ docker context use orbstack orbstack Current context is now "orbstack"
OrbStackはデフォルトで Rosetta2 を使用してくれるようで、設定は不要です。
また OrbStack は Docker Desktop のデータをマイグレートできる機能があるため、すぐに試すことができます。(Docker Desktop から乗り換えてほしいという思いを強く感じますね。)
下記画像に示すボタン、もしくはCLI (orb migrate docker
を実行)、もしくはアプリケーションのメニューバーで File > Migrate Docker Data から行うことができます。
それでは移行ができたところで、開発環境を立ち上げてみましょう。
するとwebpackのビルド時間は
Time: 375708ms
となりました。
ファイル更新時のビルド時間は
Time: 12278ms
となりました。
結論 “Docker Desktop vs OrbStack”
結果を以下に示します。グラフ中の数値はそれぞれの環境での webpack のビルド時間です。
- OrbStack を使用することで、元々の Docker Desktop を使用していたときの約2倍のビルド速度になりました。
- Docker Desktop に関しては QEMU を使用するよりも Rosetta2 を使用するほうがビルド時間は短くなりました。
- Docker Desktop と OrbStack は両者 Rosetta2 を使用すると、 OrbStack のほうが高速でした。
おわりに
今後、プロジェクトへの新規参入者は Apple シリコンのマシンを利用すると思うので、ビルド時間を早くし開発体験の向上ができたのは非常に良かったです。今のところ Docker Desktop の代替品として OrbStack の使用を検討していますが、今後も両者の動向を追っていきたいと思います。
この記事が Apple シリコン macOS ユーザーの為になったら幸いです。
最後までご覧いただきありがとうございました。