私のチームはDockerfileからRailsアプリケーションをホストしています。ビルドが実際に遅くなっている遅いgemがいくつかあります(私はyou grpc
を見ています。??? ?)
GemfileをDockerfileにコピーする前にいくつかのgemをインストールすることは可能ですか?これにより、Dockerがそれらのビルドステップをキャッシュできるようになるため、Gemfileが変更されるたびに遅いgemを再インストールする必要はありません。
私はこれを試しましたが、bundle install
はまだgrpc
、sassc
、nokogiri
をインストールしています。
RUN gem install grpc --version 1.28.0
RUN gem install sassc --version 2.2.1
RUN gem install nokogiri --version 1.10.9
WORKDIR /app
ADD Gemfile Gemfile.lock .Ruby-version /app/
RUN bundle install
オプションバンドルのインストール--deploymentまたは--pathを使用して、gemsをインストールできるフォルダーを指定できます(この目的のためにのみコンテナーを構築し、そのフォルダーをdocker外にコピーします)。次に、このディレクトリをコンテナ内のボリュームとしてマッピングし、マッピングが完了した後でバンドルインストールを実行します...または単にフォルダをコピーします:
# outside actual image
bundle install --path=vendor/cache
# actual docker image
COPY . /app
COPY vendor/cache /app/vendor/cache
COPY .bundle /app/.bundle
WORKDIR /app
RUN bundle install --path=vendor/cache
--path = vendor/cacheを指定したコマンドは、次のようにバンドル構成を生成します。
---
BUNDLE_DEPLOYMENT: "true"
BUNDLE_PATH: "vendor/cache"
コンパイルされた拡張機能のgemsバージョンがGemfileで変更されない限り、それらを再インストールしないでください。
ベンダー/キャッシュフォルダーをソースファイルにコミットしないようにするには、どこかにホストし、開発者にダウンロードしてもらうことができます。このフォルダをどこに残して、どのように画像にコピーするかは、かなり自由度の高い問題であり、何かを推奨するには、セットアップに関する詳細情報が必要です。アプリを実際にどこで本番環境にデプロイしていますか?
例:
ネイティブ拡張を備えたAWSラムダgemには問題があります。OSシステム内にインストールすることはできますが、ラムダ環境と互換性がありません。
機能するgemバンドルを作成する方法は、次のとおりです。
1-ラムダと互換性のある方法でネイティブ拡張を使用してgemをインストールするコンテナーを使用します。
docker run --rm -v "$PWD":/var/task lambci/lambda:build-Ruby2.7 bundle install --deployment
2-次に、別のコンテナでGEMSをボリュームとしてマップするか、コピーして、アプリケーションを実行します
docker run --rm --env-file=.env -v $PWD:/var/task:ro,delegated lambci/lambda:Ruby2.7 send.lambda_handler
ここでは、アプリケーションに対して同様のことを行うことをお勧めします。1つのイメージを使用してプラットフォームの宝石を構築し、次に別のイメージを使用してアプリケーションを実行し、これらの宝石をアプリケーションに渡します。 これら2つのイメージが同じOSである限り、gemは互換性があります。
これと同様の設定が、Docker以外のデプロイメントパイプラインで私のチームに機能しており、新しいバージョンをプッシュする前にgemをプリインストールし、そこからgemを取得するためにバンドルをセットアップします。