Cloud Native Buildpacksを使ってRails 7のDockerイメージを作成する(2)

はじめに

先日、「Cloud Native Buildpacksを使ってRails 7のDockerイメージを作成する」ということを記しました。今回はその続きで、細かいところを実装してみます。

miyohide.hatenablog.com

builderにheroku/builder:22を指定する

Herokuが提供しているbuidlerをみると以前試した時のものに加えてheroku/builder:22というものが提供されていることを知りました。

github.com

今回は、heroku/builder:22を使ってbuildしてみました。

$ pack build イメージ名 --builder heroku/builder:22
22: Pulling from heroku/builder
Digest: sha256:c8bbaf0aebba8e0ad48eac7015ef05cd49827b5c97277f1edaaf79f4e1769db7
Status: Image is up to date for heroku/builder:22
22-cnb: Pulling from heroku/heroku
Digest: sha256:01a71e4956727e3cbbf27b9e3f8408187ea070a8e49e3e5ad101af0c7959bc7f
Status: Image is up to date for heroku/heroku:22-cnb
===> ANALYZING
Image with name "イメージ名" not found
===> DETECTING
heroku/nodejs-engine 0.8.20
heroku/nodejs-yarn   0.4.1
heroku/jvm           1.0.9
heroku/ruby          2.0.0
heroku/procfile      2.0.0
===> RESTORING
===> BUILDING

[Heroku Node.js Engine Buildpack]

[Checking Node.js version]
Detected Node.js version range: *
Resolved Node.js version: 20.0.0

[Installing Node.js distribution]
Downloading Node.js 20.0.0
Extracting Node.js 20.0.0
Installing Node.js 20.0.0

[Detecting yarn CLI version to install]
No yarn engine range detected in package.json, using default ({DEFAULT_YARN_REQUIREMENT})
Resolved yarn CLI version: 1.22.19

[Installing yarn CLI]
Downloading yarn 1.22.19
Extracting yarn 1.22.19
Installing yarn 1.22.19
Yarn CLI operating in yarn 1.22.19 mode.

[Setting up yarn dependency cache]
yarn config v1.22.19
success Set "cache-folder" to "/layers/heroku_nodejs-yarn/deps/cache".
Done in 0.04s.

[Installing dependencies]
yarn install v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
Done in 20.49s.

[Running scripts]
Running `build` script
yarn run v1.22.19
$ webpack --config webpack.config.js
asset application.js 630 KiB [emitted] (name: application) 1 related asset
asset actioncable.js 30.1 KiB [emitted] (name: actioncable) (id hint: vendors) 1 related asset
runtime modules 6.97 KiB 11 modules
modules by path ./node_modules/ 526 KiB 94 modules
modules by path ./app/javascript/ 2.18 KiB
  ./app/javascript/application.js 191 bytes [built] [code generated]
  ./app/javascript/controllers/index.js 532 bytes [built] [code generated]
  ./app/javascript/controllers/application.js 220 bytes [built] [code generated]
  ./app/javascript/controllers/gantt_controller.js 541 bytes [built] [code generated]
  ./app/javascript/controllers/modal_controller.js 336 bytes [built] [code generated]
  ./app/javascript/controllers/todo_controller.js 408 bytes [built] [code generated]
webpack 5.80.0 compiled successfully in 1861 ms
Done in 2.50s.

[Installing OpenJDK]

[Installing Heroku JVM metrics agent]

[Heroku Ruby buildpack]
Running Heroku Ruby buildpack

[Setting environment]
Setting default environment values
Done (0.001s)

[Detecting versions]
Detected ruby: 3.2.2
Detected bundler: 2.4.10
Done (0.001s)

[Installing Ruby]
Installing ruby 3.2.2
Done (3.833s)

[Installing Bundler]
Installing bundler 2.4.10
Done (0.666s)

[Installing dependencies]
Running 'bundle install'

Running command:
$ BUNDLE_BIN="/layers/heroku_ruby/gems/bin" BUNDLE_CLEAN="1" BUNDLE_DEPLOYMENT="1" BUNDLE_GEMFILE="/workspace/Gemfile" BUNDLE_PATH="/layers/heroku_ruby/gems" BUNDLE_WITHOUT="development:test" bundle install
Fetching gem metadata from https://rubygems.org/.........
Fetching rake 13.0.6
Installing rake 13.0.6
(省略)
Bundle complete! 26 Gemfile dependencies, 64 gems now installed.
Gems in the groups 'development' and 'test' were not installed.
Bundled gems are installed into `/layers/heroku_ruby/gems`
Done (20.660s)

[Detecting gems]
Detecting gems via `bundle list`
Done (0.256s)

[Setting default process(es)]
Detected railties gem
Setting default web process (rails)
Done (0.000s)

[Rake task detection]
Rake gem found
Rakefile found at /workspace/Rakefile
Detecting rake tasks via `rake -P`
Done (1.931s)

[Rake asset installation]
Running 'rake assets:precompile', task found
Running 'rake assets:clean', task found
Creating cache for /workspace/public/assets
Creating cache for /workspace/tmp/cache/assets

Running command:
$ bundle exec rake assets:precompile assets:clean --trace
** Invoke assets:precompile (first_time)
** Invoke assets:environment (first_time)
** Execute assets:environment
** Invoke environment (first_time)
** Execute environment
** Invoke javascript:build (first_time)
** Execute javascript:build
yarn install v1.22.19
[1/4] Resolving packages...
success Already up-to-date.
Done in 0.20s.
yarn run v1.22.19
$ webpack --config webpack.config.js
asset application.js 630 KiB [compared for emit] (name: application) 1 related asset
asset actioncable.js 30.1 KiB [compared for emit] (name: actioncable) (id hint: vendors) 1 related asset
runtime modules 6.97 KiB 11 modules
modules by path ./node_modules/ 526 KiB 94 modules
modules by path ./app/javascript/ 2.18 KiB
  ./app/javascript/application.js 191 bytes [built] [code generated]
(省略)
webpack 5.80.0 compiled successfully in 1801 ms
Done in 2.38s.
** Invoke css:build (first_time)
** Execute css:build
yarn install v1.22.19
[1/4] Resolving packages...
success Already up-to-date.
Done in 0.15s.
yarn run v1.22.19
$ sass ./app/assets/stylesheets/application.bootstrap.scss:./app/assets/builds/application.css --no-source-map --load-path=node_modules
Done in 3.10s.
** Execute assets:precompile
W, [2023-05-07T02:21:05.317451 #453]  WARN -- : Removed sourceMappingURL comment for missing asset 'bootstrap.esm.js.map' from /workspace/app/assets/builds/application.js
(省略)
** Invoke assets:clean (first_time)
** Invoke assets:environment
** Execute assets:clean
Storing cache for /workspace/public/assets
Storing cache for /workspace/tmp/cache/assets
Done (8.792s)

[Heroku Ruby buildpack finished]
Finished (36.143s total elapsed time)


[Discovering process types]
Procfile declares types -> web, release
===> EXPORTING
Adding layer 'heroku/nodejs-engine:dist'
Adding layer 'heroku/nodejs-engine:web_env'
Adding layer 'heroku/nodejs-yarn:deps'
Adding layer 'heroku/nodejs-yarn:dist'
Adding layer 'heroku/jvm:heroku_metrics_agent'
Adding layer 'heroku/jvm:openjdk'
Adding layer 'heroku/jvm:runtime'
Adding layer 'heroku/ruby:bundler'
Adding layer 'heroku/ruby:cache_public_assets'
Adding layer 'heroku/ruby:cache_tmp_cache_assets'
Adding layer 'heroku/ruby:env_defaults'
Adding layer 'heroku/ruby:gems'
Adding layer 'heroku/ruby:ruby'
Adding layer 'buildpacksio/lifecycle:launch.sbom'
Adding 1/1 app layer(s)
Adding layer 'buildpacksio/lifecycle:launcher'
Adding layer 'buildpacksio/lifecycle:config'
Adding layer 'buildpacksio/lifecycle:process-types'
Adding label 'io.buildpacks.lifecycle.metadata'
Adding label 'io.buildpacks.build.metadata'
Adding label 'io.buildpacks.project.metadata'
Setting default process type 'web'
Saving イメージ名...
*** Images (0f6686f5220b):
      イメージ名
Adding cache layer 'heroku/nodejs-engine:dist'
Adding cache layer 'heroku/nodejs-yarn:deps'
Adding cache layer 'heroku/nodejs-yarn:dist'
Adding cache layer 'heroku/jvm:heroku_metrics_agent'
Adding cache layer 'heroku/jvm:openjdk'
Adding cache layer 'heroku/ruby:bundler'
Adding cache layer 'heroku/ruby:cache_public_assets'
Adding cache layer 'heroku/ruby:cache_tmp_cache_assets'
Adding cache layer 'heroku/ruby:gems'
Adding cache layer 'heroku/ruby:ruby'
Successfully built image イメージ名

イメージサイズを確認すると、以前利用したheroku/buildpacks:20に比べてサイズは大きく増えました(878MB->1.2GB)。

$ docker images
REPOSITORY          TAG       IMAGE ID       CREATED         SIZE
heroku/heroku       20-cnb    a92beb087570   34 hours ago    633MB
heroku/heroku       22-cnb    8c10df59875b   34 hours ago    647MB
heroku/builder      22        07a24bb47d10   43 years ago    1.11GB
heroku/builder:22で作成したイメージ     0.0.1     4234cda699f0   43 years ago    1.2GB
heroku/buildpacks   20        e1b1d378f6b5   43 years ago    1.69GB
heroku/buildpacks:20で作成したイメージ    0.0.2     6bf07e0d196d   43 years ago    878MB
$

イメージの作成作成時間を今の時間に変更する

pack buildでイメージを作成したとき、デフォルトではCREATED43 years agoとなります。これは、イメージの再利用などを考慮したものだそうです。詳細は以下の記事を参照。

medium.com

これを変更して今の時間に変更するにはpack buildコマンドに--creation-time nowオプションを指定します。オプションのマニュアルは以下を参照してください。

buildpacks.io

実際にオプションを指定してみるとCREATEDの時間が43 years agoではないことが確認できました。

$ docker images
REPOSITORY          TAG       IMAGE ID       CREATED         SIZE
オプション指定     0.0.4     0f6686f5220b   3 minutes ago   1.2GB
オプション未指定     0.0.1     4234cda699f0   43 years ago    1.2GB
$

設定ファイルを作成して、イメージに含めないファイルを指定する

設定ファイルproject.tomlというものを作成するとイメージに含めないファイルを指定することができます。

buildpacks.io

詳細な仕様はGitHub上にもあるのでそこも確認しておきます。

github.com

みたところ、schema-version = "0.2"の記述が公式サイトには抜けているようでした。

そこで、以下のようにproject.tomlを記述しました。

[_]
schema-version = "0.2"
id = "myapp"
version = "0.1"

[io.buildpacks]
builder = "heroku/builder:22"
exclude = [
    ".git",
    "node_modules",
    "docs",
    "README.md"
]

これでpack build イメージ名を実行することで、excludeに指定したファイルたちがイメージ内に含まれないことが確認できました。