Play Framework アプリケーションの slug のサイズの削減
最終更新日 2023年11月29日(水)
Table of Contents
Git を使用してデプロイするとき、非常に大規模な Play アプリケーションでは、プラットフォームの slug サイズ制限を超えることがよくあります。これが発生した場合、デプロイ時に次のようなエラーが表示されます。
remote: ! Compiled slug size 583.3MB is too large, max is 500 MB.
この問題を解決するには、Git を使用しないデプロイに切り替えるなど、いくつかの方法があります。この記事では、これを実践する方法と、アプリケーションの設定によってその slug サイズを削減する方法について説明します。
sbt-native-packager の使用
sbt-native-packager プラグインを使用すると、buildpack で、slug をコンパイルする前に不要な sbt キャッシュを消去できます。これは非推奨になった sbt-start-script プラグインを置き換えるもので、Play フレームワークの最新バージョンですでに使用されています。Play で sbt-native-packager を使用するには、このプラグインが最初から含まれている、Play の バージョン 2.2 または 2.3 にアップグレードする必要があります。次に、Procfile
を変更して次の内容を追加します。
web: target/universal/stage/bin/my-app -Dhttp.port=${PORT}
アプリケーションによっては、-DapplyEvolutions.default=true
をコマンドに含めることが必要な場合もあります。
スタンドアロンアプリケーションの場合、次の内容を project/plugins.sbt
に追加します。
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "0.8.0-RC2")
そして、次の内容を build.sbt
に追加します。
import NativePackagerKeys._
ここで sbt stage
を実行すると、アプリケーションの実行に必要なすべてのものがプラグインによって target/universal/stage
ディレクトリにパッケージ化されます。これにより、buildpack は他のすべての一時的なアセットを slug から削除できます。
web
ターゲットの名前変更
Play では、Web アセットを target/web
ディレクトリにパッケージ化します。buildpack はデフォルトでこれらを削除しませんが、アプリケーションの設定により、それらを削除しても問題がないことを buildpack に指示できます。これを行うには、次の内容を build.sbt
に追加します。
WebKeys.webTarget := target.value / "scala-web"
artifactPath in PlayKeys.playPackageAssets := WebKeys.webTarget.value / (artifactPath in PlayKeys.playPackageAssets).value.getName
これにより、web
ターゲットディレクトリの名前が scala-web
に変更され、アセットのアーティファクトがそのディレクトリに移動します。このようにすれば、buildpack でアセットを slug から安全に削除できます。
.slugignore
ファイルの追加
実行時に必要のないバイナリやその他の大きなファイルが Git リポジトリに含まれている場合、Git リポジトリのルートに .slugignore
ファイルを作成することによって、それらを slug から除外することができます。
テストの実行時にしか必要でない大きなファイルが Git リポジトリに含まれていることはよくあります。この場合、.slugignore
ファイルは次のようになります。
*.psd
*.pdf
/test
heroku run bash
を実行し、ls
や du
などのコマンドを使用して、slug の抽出された内容を調査できます。これは、.slugignore
ファイルに追加する必要がある大きなファイルを特定するのに役立つ場合があります。具体的に何を除外してもよいのかは、各アプリケーションのニーズによって異なります。
sbt を使用してビルドアーティファクトをクリーンアップする
この方法は、実行時に必要でない大きなアーティファクトがビルドで作成される場合や、コンパイル時には必要だが実行時には必要でない大きなファイルがプロジェクトに含まれている場合に役立ちます。
build.sbt
ファイルに次のコードを追加します。
val stage = taskKey[Unit]("Stage and clean task")
stage := {
(stage in Universal).value
if (sys.env.getOrElse("POST_STAGE_CLEAN", "false").equals("true")) {
println("cleaning...")
sbt.IO.delete(baseDirectory.value / "my-subdir")
}
}
これにより、sbt-native-packager プラグインによって提供されるデフォルトの stage
タスクが上書きされ、いくつかの新しい動作が追加されます。カスタムの stage
タスクの本体の最初の行では、元の stage
タスクを sbt-native-packager (stage in Universal
) から呼び出します。次に、sbt がプロジェクトをローカルで削除することを防ぐ POST_STAGE_CLEAN
環境設定をチェックします。この環境設定が true
に設定されている場合、タスクの残りの部分でプロジェクトファイルを削除できます。
上記のコードを Git リポジトリに追加したら、次のように環境設定を行う必要があります。
$ heroku config:set POST_STAGE_CLEAN="true"
Heroku にプッシュすると、ステージングタスクが実行され、それに従ってプロジェクトがクリーンアップされます。
以上の提案を実装しても slug のサイズがまだ大きすぎる場合は、Heroku サポートにお問い合わせください。