はじめに
Rails 7.1 1 がリリースされ、rails new
を実行した際に Dockerfile
を自動生成してくれるようになったと聞いて、真っ先に思ったのは、
デファクトスタンダード的に、ベースとできるものがあれば「 そこからの変更には、明確な理由を必須とする 」ような方針を取れるので、
複数のリソースからのコピペによって合成されたキメラ Dockerfile
を卒業し、より安心感のある環境が構築しやすくなりそうだ、ということでした。
また、本番環境での使用に向けて調整されているとのことなので、そういう意味でも、非常に参考になりますね。
雑に生成してみる
さて、何はともあれ、試してみましょう。2
できるだけ、ローカル( ホスト )環境には依存したくないし、実行環境をわかりやすくするためにも、Ruby 3 の公式イメージなどを利用した Docker コンテナ上で作業するのがオススメです。
とは言え、生成されたファイル群は、ホスト側にも欲しかったので、適当なディレクトリを用意してマウントしています。
docker run --rm -it -v .:/app -w /app ruby:3.2.2 bash
では、rails
をインストールして、rails new
を実行してみましょう。
gem install rails
↓( バージョンを確認 )
# rails --version
Rails 7.1.3
↓
rails new . --database=postgresql --css=bootstrap
せっかくなので、database
と css
も指定しておきました。
まさか、そのせいで、ちょっとしたエラーが出て、そのおかげで、自動生成についての理解が深まるなどとは、夢にも思っていませんでしたが。
そうでなければ、このテーマだけで記事を書くこともなかったかもしれません。4
試行錯誤してみる
無事に rails new
できたでしょうか?
私はと言うと、一応、Dockerfile
は生成されているものの、こんなエラーに遭遇してしまいました。
Rails::Generators::Error: The template [/usr/local/bundle/gems/cssbundling-rails-1.4.0/lib/install/bootstrap/install.rb] could not be loaded. Error: No such file or directory - npx (Rails::Generators::Error)
おそらく、調子に乗って Bootstrap を追加しようとしたため、要求される環境が多少なりとも厳しくなったからですね。
まぁ、もし( Node 環境の整った )ホスト環境で実行していたら、このエラーは気付かないうちに回避されていたかもしれないのですが、
考えてみれば「 オプションや環境が異なる場合、自動生成される Dockerfile
にどのような違いが生まれてくるのか 」というのも、気になるところではあります。
いい機会なので、ちょっと色々と試してみることにしましょう。
css
オプションの確認
まず、css
オプションを指定しなかったらどうなるのか?
rails new . --database=postgresql
この場合、エラーは出ることなく完了しますが、当然、package.json
などのファイルは生成されず、Dockerfile
にも、以下のような違いが生じるようです。
% diff after/Dockerfile before/Dockerfile
20c20
< # Install packages needed to build gems
---
> # Install packages needed to build gems and node modules
22c22,31
< apt-get install --no-install-recommends -y build-essential git libpq-dev libvips pkg-config
---
> apt-get install --no-install-recommends -y build-essential curl git libpq-dev libvips node-gyp pkg-config python-is-python3
>
> # Install JavaScript dependencies
> ARG NODE_VERSION=18.15.0
> ARG YARN_VERSION=latest
> ENV PATH=/usr/local/node/bin:$PATH
> RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
> /tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
> npm install -g yarn@$YARN_VERSION && \
> rm -rf /tmp/node-build-master
28a38,41
>
> # Install node modules
> COPY package.json yarn.lock ./
> RUN yarn install --frozen-lockfile
言われてみれば、当たり前の話なのですが、単に「 JavaScript の依存関係と Node モジュールのインストールなどを実行するかどうか 」が異なり、要するに css
オプションを指定する場合には、Node 環境も利用することになります。
まぁ、開発を進めているうちに、後から Node が必要になって、Dockerfile
に追記する場合などには、この情報( 記述 )も役に立つかもしれませんね。
Node 環境の確認
次に、少し気になったのは、Node を含む場合の、そのバージョンについてです。
こちらも、実に単純な話なのですが、色々と試していると、環境によって Node のバージョン指定が異なってくることがわかります。
自動生成された Dockerfile
で、NODE_VERSION
という環境変数に入っている値ですね。
試しに、rails new
する前に、次のようにして npm をインストールしておきましょう。
apt-get update -qq && apt-get install --no-install-recommends -y npm
ついでに、バージョンも現時点で最新の LTS に更新しておきました。
npm install -g n
n lts
hash -r
↓( バージョンを確認 )
# node --version
v20.11.0
この状態で、最初の時と同じように rails new
を実行すると、どうでしょう?
前のようにエラーが出ることもなく、以下のように Dockerfile
を比較してみるとわかりますが、どうやら、実行環境の Node のバージョンを反映してくれているようです。
% diff before/Dockerfile after/Dockerfile
25c25
< ARG NODE_VERSION=18.15.0
---
> ARG NODE_VERSION=20.11.0
というか、エラーが出た時の、デフォルト?のバージョンは 18.15.0
なんですね。
まぁ、エラーが出たならともかく、バージョンを上げたくなったら書き換えればいいだけの話なのですが、場合によっては、他に影響がないかどうか、注意が必要かもしれません。
そして、今度は package.json
などにも、何やらちゃんと記述してくれています。
ありがとう、Rails!
% diff before/package.json after/package.json
3,4c3,13
< "private": "true"
< }
---
> "private": "true",
> "scripts": {
> "build:css:compile": "sass ./app/assets/stylesheets/application.bootstrap.scss:./app/assets/builds/application.css --no-source-map --load-path=node_modules",
> "build:css:prefix": "postcss ./app/assets/builds/application.css --use=autoprefixer --output=./app/assets/builds/application.css",
> "build:css": "yarn build:css:compile && yarn build:css:prefix",
> "watch:css": "nodemon --watch ./app/assets/stylesheets/ --ext scss --exec \"yarn build:css\""
> },
> "browserslist": [
> "defaults"
> ]
> }
Yarn 環境の確認
いや、ちょっと待って、Rails!
エラーは出なくなりましたが、package.json
をよく見てみると、Bootstrap の利用に必要な依存関係などは、何も追加されていませんね。
確か、ちゃんと環境が整っていれば、rails new
した際に、そこまで追記してくれていたはずです。
というか、昔は Yarn がないと、エラーが出ていたような気もしますし、先に( Node と一緒に )インストールしておくパターンも試してみましょう。
npm install --global yarn
↓( バージョンを確認 )
# yarn --version
1.22.21
さて、この状態で rails new
を実行した場合、どうなるでしょうか?
そう言えば、Dockerfile
にも、Node と同様、バージョンを指定するための環境変数が用意されていましたが、実行環境のバージョンを反映してくれる点も、同じようですね。5
# diff before/Dockerfile after/Dockerfile
26c26
< ARG YARN_VERSION=latest
---
> ARG YARN_VERSION=1.22.21
では、果たして、package.json
の中身は、どうなっているのか。
# cat package.json
{
"name": "app",
"private": "true",
"dependencies": {
"@popperjs/core": "^2.11.8",
"autoprefixer": "^10.4.17",
"bootstrap": "^5.3.2",
"bootstrap-icons": "^1.11.3",
"nodemon": "^3.0.3",
"postcss": "^8.4.33",
"postcss-cli": "^11.0.0",
"sass": "^1.70.0"
},
"scripts": {
"build:css:compile": "sass ./app/assets/stylesheets/application.bootstrap.scss:./app/assets/builds/application.css --no-source-map --load-path=node_modules",
"build:css:prefix": "postcss ./app/assets/builds/application.css --use=autoprefixer --output=./app/assets/builds/application.css",
"build:css": "yarn build:css:compile && yarn build:css:prefix",
"watch:css": "nodemon --watch ./app/assets/stylesheets/ --ext scss --exec \"yarn build:css\""
},
"browserslist": [
"defaults"
]
}
エクセレント!!
ちなみに、ここまでやって初めて、node_modules
ディレクトリや、yarn.lock
ファイルなども追加されるようなので、これらの環境が必要な場合には、注意してみてください。
まとめ
結論としては、特に CSS フレームワークをオプションで指定する場合などには、Node & Yarn 環境を確認してから、rails new
すればいい、ということですね。
ともあれ、Docker を使えば、気軽に様々な環境を作って自動生成を行えるので、何か気になることがあったら、実際に色々と試してみることをオススメします。
最後に、今回とてもお世話になった「 二つのディレクトリを指定して、簡単にファイル群を比較するコマンド 」を紹介して、締めとさせていただきましょう。
# diff -rq -x tmp -x .DS_Store before after
Files before/Dockerfile and after/Dockerfile differ
Only in after/app/assets/builds: application.css
Files before/config/credentials.yml.enc and after/config/credentials.yml.enc differ
Files before/config/master.key and after/config/master.key differ
Only in after: node_modules
Files before/package.json and after/package.json differ
Only in after: yarn.lock
ありがとう、diff!
-
https://rubyonrails.org/2023/10/5/Rails-7-1-0-has-been-released ↩
-
ちなみに、本記事の執筆時に利用している PC は、MacBook Pro( 14-inch, M2 Pro, 2023 )で、macOS Sonoma 14.3( Docker version 24.0.7 )環境です。 ↩
-
YARN_VERSION
のデフォルトがlatest
だというのは、まぁ、妥当なのでしょうかね? ↩