LoginSignup
2
1

Ruby on Rails 7.1 で Dockerfile を自動生成してみた!

Last updated at Posted at 2023-10-25

はじめに

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

せっかくなので、databasecss も指定しておきました。

まさか、そのせいで、ちょっとしたエラーが出て、そのおかげで、自動生成についての理解が深まるなどとは、夢にも思っていませんでしたが。

そうでなければ、このテーマだけで記事を書くこともなかったかもしれません。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!

  1. https://rubyonrails.org/2023/10/5/Rails-7-1-0-has-been-released

  2. ちなみに、本記事の執筆時に利用している PC は、MacBook Pro( 14-inch, M2 Pro, 2023 )で、macOS Sonoma 14.3( Docker version 24.0.7 )環境です。

  3. https://hub.docker.com/_/ruby

  4. 生成された Dockerfile の全貌が気になる方は、次回の記事 をご参照ください。

  5. YARN_VERSION のデフォルトが latest だというのは、まぁ、妥当なのでしょうかね?

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1