概要
- RustアプリのDockerデプロイでビルド時間の問題に直面
- 標準的なDockerビルドでは毎回フルビルドが発生し非効率
- cargo-chefなどのキャッシュ戦略で依存関係の再ビルドを削減
- ビルド時間の大半はLTOやLLVMの最適化処理に集中
- ltoやdebug設定の調整でビルド速度・バイナリサイズのバランス改善可能
RustアプリをDockerで高速にビルド・デプロイしたい話
- Rust製Webサイト のデプロイを従来の「静的バイナリ転送+再起動」から Dockerコンテナ方式 へ移行を決意
- 普通のDockerfile (rust:alpineイメージ+muslターゲット)では 毎回全ビルド が走り、4分以上かかる現実
- cargo-chef を利用し、依存クレートのビルドを キャッシュレイヤ として分離
- 依存関係に変更がなければ再ビルド不要
- しかし、アプリ本体のビルド時間が依然として長い(2分50秒など)
- 依存関係ビルド は全体の25%程度、 本体ビルド が大半を占める傾向
rustcのビルド時間の内訳調査
- cargo --timings でビルド各工程の所要時間を可視化
- ただし最終クレートのビルド時間しか興味がない場合は情報が限定的
- rustcの自己プロファイリング(-Zself-profile) をRUSTFLAGS経由で有効化
- measuremeツール群(summarize, flamegraphなど)で詳細解析
- LTO(Link Time Optimization) と LLVM_module_codegen_emit_obj が大半の時間を消費
- codegen_module_perform_ltoが全体の80%近くを占めるケース
LTOとデバッグ設定の影響
- Cargo.tomlで lto = "thin"、 debug = "full" などを設定していたことが判明
- LTOの種類(off/thin/fat)やdebug情報の粒度で ビルド時間とバイナリサイズが大きく変動
- LTOを無効化 するとビルドが高速化
- ただし最適化レベルやバイナリサイズ、実行速度とのトレードオフが発生
DockerでのRustビルド高速化Tipsまとめ
- 依存関係のキャッシュ にはcargo-chefが有効
- ただしアプリ本体のビルド最適化も不可欠
- LTOやdebugの設定 を見直し、用途に応じた最適バランスを選択
- rustcの自己プロファイリング を活用し、ボトルネック特定
- ビルド時間短縮 と パフォーマンス確保 のバランス調整が重要
まとめ
- DockerでのRustビルド高速化 には、依存関係キャッシュと本体ビルド最適化の両立が必要
- LTOやdebug設定の見直し で大幅な時間短縮が可能
- measuremeツール で詳細なプロファイリング・分析が有効
- 最適化の落とし所 はアプリの特性や運用フローに依存
- 継続的な ビルド戦略の改善 が効率的な開発・運用の鍵