Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails: Dockerマルチステージビルドでgemをキャッシュする(翻訳)

概要

元サイトの許諾を得て翻訳・公開いたします。

Rails: Dockerマルチステージビルドでgemをキャッシュする(翻訳)

Railsのビルドでは、Dockerfileのbundle installにかかる時間が大半を占めます。

以下は、あるRailsアプリケーションの標準的なDockerfileを簡略化したものです。

FROM ruby:3.1.2

RUN gem install bundler:2.3.7

WORKDIR /app

COPY Gemfile Gemfile.lock ./

RUN bundle install
COPY . .

このDockerfileでは、ソースコードをコピーする前にビルドキャッシュを使ってGemfileとGemfile.lockを分離しています。

gemがインストールされるのは最初のビルドだけなので、この方法は非常に有効です。

非Docker環境と異なるのは、Gemfileやgemを変更したりgemを追加・削除したりすると、すべてのgemが最初から再インストールされることです。

キャッシュイメージを使う

RUN gem install bundler:2.3.7

WORKDIR /app

# Copy the gems from a dedicated cache image
COPY --from saeloun:rails7:gem-cache /usr/local/bundle /usr/local/bundle
COPY Gemfile Gemfile.lock ./

RUN bundle install
COPY . .

上は、saeloun:rails7:gem-cacheイメージの/usr/local/bundleディレクトリを自分たちのビルドにコピーします。

COPY --fromを指定すると、Dockerはファイルを既存のレジストリから現在のビルドにコピーできます。これにより、Bundlerの実行をやり直さなくなり、前回使ったすべてのgemがキャッシュされるようになります。

唯一の問題は、イメージがそのレジストリ内に存在していないと動作しないことです。この方法は、初期のビルドイメージが存在しない場合は失敗します。

マルチステージでgemをキャッシュする

マルチステージビルドを使うと、Dockerfileをさらに改善してレジストリをdocker buildの引数として渡せるようになります。

ARG BASE_IMAGE=ruby:3.1.2
ARG CACHE_IMAGE=${BASE_IMAGE}

# gemキャッシュ用のビルドステージ
FROM ${CACHE_IMAGE} AS gem-cache
RUN mkdir -p /usr/local/bundle

# Bundlerインストール済みのイメージ
FROM $BASE_IMAGE AS base
RUN gem install bundler:2.3.7
WORKDIR /usr/src/app

# gemキャッシュ用のビルドステージからgemをコピーする
FROM base AS gems
COPY --from=gem-cache /usr/local/bundle /usr/local/bundle
COPY Gemfile Gemfile.lock ./
RUN bundle install

# ソースコードを配置する
FROM base AS deploy
COPY --from=gems /usr/local/bundle /usr/local/bundle
COPY . .

このビルドステージには以下の4つのステップがあります。

  1. gem-cache: gem-cache用のディレクトリを作成する
  2. base: Bundlerをインストールする
  3. gem: gemを既存のイメージからコピーしてBundlerを実行する
  4. deploy: ソースコードを追加する

CACHE_IMAGEが設定されていないと/usr/local/bundleの内容が空になり、gemをコピーできなくなります。CACHE_IMAGEにgem入りのイメージが設定されていれば、gemはコピーされます。

これで、以下を実行してイメージをビルドできるようになります。

docker build .

タグが設定された後は、CACHE_IMAGEを以下のように設定できます。

docker build .  --build-arg CACHE_IMAGE=saeloun:rails7:gem-cache app

関連記事

クジラに乗ったRuby: Evil Martians流Docker+Ruby/Rails開発環境構築(更新翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。