Dockerイメージのサイズ削減と開発改善の話

はじめに

こんにちは。EventHubの西内です。

EventHubというサービスは2019年7月にリリースされ、まだまだ開発したい機能はあるものの、ある程度の顧客ニーズをカバーできるぐらいには機能が出揃って来たという状況です。

一方で、サービスが成長・拡大していく中で、最新技術への継続的なアップデートや、さらに高いパフォーマンスを出すための最適化など、中長期的な視点で取り組むべき課題も生まれてきました。

そういった背景や状況を踏まえ、顧客へ直接的な価値を提供する機能開発をやりつつも、「開発改善」を行う時間の割合を増やすことにしました。

そのうちの施策の1つとして、今回はDockerイメージのサイズ削減に取り組んだ話について少し触れていこうと思います。

Dockerイメージのサイズ削減

前提として、EventHubではフロントエンドもバックエンドもTypeScriptを採用しており、さらにyarn workspaceを利用したmonorepoでの管理を行っています。複数のワークスペースのうちの1つがAPIサーバー(とBatch処理)を担っています。 今回はそのAPIサーバーが利用するimageのサイズを小さくしようという話になります。

方針として「比較的安全にDockerイメージのサイズを削減する」ことにしました。

Dockerイメージに関わる課題感はいくつか思い浮かぶものがあるとは思いますが、サイズ削減だけにフォーカスしたのは改善前の時点でイメージのサイズが約5GBにもなっていたためです。

また、比較的安全としているのは、サイズ削減を突き詰めることはせず、なるべく少ないコストやリスクで出来るだけ大きいリターンを得たいためです。

さて、Dockerfileの改善をしたことのある方が読んでいるとしたら、おおよその原因や解決策がイメージできているのかなと思います。自分も事前にある程度イメージできてはいますが、昨今のAI活用の波に乗り、今回はせっかくなのでGitHub Copilot + GPT-5.2-Codex(以下、AI)の組み合わせで対応してみることにしました。

方針と効果検証

AIにやりたいことを伝えてやりとりした結果、以下の方針が提案されました。

方針 目的 効果 コスト リスク
A: マルチステージ ビルド成果物と実行環境の分離
B: slim ベース OS レイヤー削減
C: 依存最小化 Workspaces 範囲の縮小
D: キャッシュ削除 キャッシュ・不要ファイルの削除 小〜中

イメージサイズを削減する方法として、ざっくり4パターンあるということになります。ただ単に小さくするだけなら、これらすべてをやればいいだけなのですが、パターンごとにどれぐらい効果が異なるのかをAIに検証してもらうことにしました。
一言お願いするだけで検証用のDockerfileの作成から実行、その結果をドキュメントに書き出してくれるのはめちゃめちゃ楽ですね。

結果としてはおおよそ上記の想定通りで、AのマルチステージとCの依存最小化がそれぞれ50%程度の削減効果がありました。

ちなみにBのベースイメージをslimにする対応は、削減割合として低い結果となりました。これは元々のイメージサイズが5GBもあり、その大部分は不要なnode_modulesが占めていたためなので、通常は手っ取り早く出来てそこそこの効果が出る方法のはずです。

具体的な方法やテクニックは巷に溢れていると思うので割愛しますが、EventHubの場合はAIの提案した内容でほとんど問題なかったです。

最終結果と副次的効果

最終的にはすべてのパターンを組み合わせて対応することとしました。

その結果として、圧縮前で約5.0GBあったイメージが約0.7GBとなりました。

さらに小さくすることは出来そうですが、そのためにはパッケージマネージャの変更や更新、そもそも不要なパッケージの削除などなど、他の対応を行う必要がありそうでした。このあたりは実際に試していないためその限りではないかも知れませんが、前述の通りなるべく少ないコストで進めたいと考えていたので、別の機会で改善することにしました。

副次的な効果に関しては、docker buildとpushの時間が短縮されました。 依存関係を縮小することでbuildの時間(主にyarn installの時間)が減り、イメージサイズが小さくなったことで単純にpushの時間も減ったという感じです。時間にして合計およそ12分から3分への改善となりました。

Before:

After:

また、Batch処理のためにAWS Batch(with Fargate)を利用しているのですが、ジョブが作成されてから開始するまでの時間も短縮されていました。こちらは約3分20秒から約50秒になりました。その分、余計なコンピューティングリソースを使わなくなったので、インフラのコスト削減にも貢献できそうです。

そういえば「開発改善」って?

そういった背景や状況を踏まえ、顧客へ直接的な価値を提供する機能開発をやりつつも、「開発改善」を行う時間の割合を増やすことにしました。

タイトルや冒頭でぬるっと出てきた「開発改善」に関して補足させてください。

EventHubにおける開発改善とは「顧客へ直接的な価値を提供する機能開発」以外と表現してしまっていいかも知れません。

それらは一体どんなものなのか。
たとえば直近で実際に対応した/している内容で言えばこんな感じですね。

  • lint設定の改善
  • インフラのバージョンアップ対応
  • CI&CDの改善
  • 肥大化したDBのテーブルを分割

これらはサービスを継続的に改善・維持するために必要な活動です。
これまでにも同様のことは行ってきておりますが、これからはより明示的に時間を使っていくこととなり、またこれらの活動はいまいち効果の見えづらいものでもあります。

そのため、EventHubでは毎週のSprintレビュー時に開発改善に関する説明を行うこととなりました。

その際には、以下4つの価値指標で発表することとしています。

指標 具体的対象(非機能要件) ビジネス価値
1. 事業継続・防衛 セキュリティ、バックアップ、可用性、冗長化 情報漏洩やシステム停止などを防ぐため
2. ユーザー体験・信頼 応答速度、スケーラビリティ 「顧客離脱の防止と満足度」「重い」「落ちる」は即座に解約理由になります。快適な動作は、機能追加以上に顧客維持(リテンション)に直結します。
3. 変更の柔軟性 修正容易性(リファクタ)、テスト自動化、疎結合 「市場への適応速度」法改正やトレンド変化に合わせて、競合より1秒でも早く新機能をリリースできる「筋肉質な組織」を作ります。
4. 運用効率・コスト 監視、ログ整備、クラウドコスト最適化 「利益率の向上」属人的なトラブル対応時間を減らし、サーバー代を削減することで、営業利益を直接的に押し上げます。

 

先ほどのDockerイメージのサイズ削減の取り組みに当てはめた場合、EventHubでは以下のように捉えております。

  • 事業継続・防衛
    • 復旧時間の短縮
  • ユーザー体験・信頼
    • 特に変わりなし
  • 変更の柔軟性
    • 特に変わりなし
  • 運用効率・コスト
    • 開発の待ち時間短縮
    • インフラコストの削減

特に1日に何度も回しているCIのインフラコストが長い目で見て効いてきそうな気がします。

おわりに

今回は開発改善にさらに力を入れ始めたよ、というお話をさせていただきました。

改めて、開発改善はこれまでもやってきたことではありますが、セキュリティイシューの対策やEOLの対応など必要最低限のものに留め、機能拡充の優先度のほうが高かったことは事実です。

しかし、そのおかげもありEventHubというプロダクトは成長・拡大してきました。

そして今後の機能拡充の速度を落とさないようにしていくためにも、今一度土台を固めていくフェーズに差し掛かっている状態です。

そんなEventHubでは機能の開発だけでなく「開発改善」にも興味のあるフルサイクルなエンジニアを募集しておりますので、興味のある方はぜひ以下のリンクから覗いてみてください!

jobs.eventhub.co.jp