Dev Container に Bundler キャッシュボリュームを追加
Dev Container 環境で Bundler の依存関係を永続化し、コンテナ起動時の gem 再インストールを回避できるようになりました。この変更は起動時間の短縮とリソース消費の削減を目的としています。
背景
従来、Dev Container を再生成するたびに Bundler が Gemfile の依存を再度インストールしており、開発サイクルが遅延していました。#53123 で導入された ghcr.io/rails/devcontainer/features/bundler-cache は同様の目的を果たしますが、追加の機能設定が必要でした。今回の PR は .rbenv ディレクトリ全体をボリュームとしてマウントすることで、設定を省略しながら同様のキャッシュ効果を実現します。これにより、開発者は Docker コンテナの再作成時でも gem が保持され、即座に作業を再開できます。
技術的な変更
compose.yaml テンプレート (railites/lib/rails/generators/rails/devcontainer/templates/devcontainer/compose.yaml.tt) に以下の行が追加され、bundle-cache ボリュームを /home/vscode/.local/share にマウントします。
volumes:
- ../../<%= app_folder %>:/workspaces/<%= app_folder %>:cached
+ - bundle-cache:/home/vscode/.local/share
上部の volumes: 定義にも bundle-cache が明示的に記載され、他のデータボリュームと同様に管理されます。
volumes:
+ bundle-cache:
<%- if !volumes.empty? -%>
<%- volumes.each do |volume| -%>
<%= volume %>:
テストコードも同様に更新され、生成された docker-compose.yml が新しいボリュームを含むことを検証しています。たとえば railtes/test/commands/devcontainer_test.rb では rails-app サービスの volumes 配列に bundle-cache:/home/vscode/.local/share が期待値として追加されています。
"volumes" => [
"../../app:/workspaces/app:cached",
+ "bundle-cache:/home/vscode/.local/share"
],
さらに devcontainer_generator_test.rb ではトップレベルの volumes キーに bundle-cache が含まれることをアサートし、他のデータベースボリュームとの共存を確認しています。
設計判断
シンプルなマウント方式 を選択した背景には、既存の Dev Container 設定に最小限の変更でキャッシュ機能を提供したいという意図があります。外部の bundler-cache フィーチャーは柔軟性が高いものの、追加のレイヤーと設定項目を必須とします。一方、.rbenv ディレクトリ全体をボリューム化することで、Bundler のキャッシュだけでなく Ruby の実行環境全体が保持され、将来的なツール追加にも自然に対応できます。トレードオフとしては、bundle-cache が他のユーザーデータを含む可能性がある点ですが、コンテナ内部のパスが限定されているため衝突リスクは低く、実装コストが大幅に削減できました。
まとめ
この PR は、Dev Container の docker-compose.yml に bundle-cache ボリュームを組み込むだけで、Bundler の依存キャッシュを自動的に利用できるようにします。設定がシンプルでテストも網羅されているため、既存の開発フローに影響を与えずに起動時間の短縮が期待できます。