RailsプロジェクトをDockerで環境構築する

概要
新規RailsプロジェクトをDockerで環境構築する。

compose.ymlの使用
docker-compose.ymlではなく、compose.ymlが推奨になった。yamlとymlについては、railsがyml(database.yml、等)なので、ymlを使用することにする。
The default path for a Compose file is compose.yaml (preferred) or compose.yml that is placed in the working directory. Compose also supports docker-compose.yaml and docker-compose.yml for backwards compatibility of earlier versions. If both files exist, Compose prefers the canonical compose.yaml.
出典:https://docs.docker.com/compose/compose-file/03-compose-file/

version指定は不要
compose.ymlには、version: '3'などのversion指定をよく見かける。然乍、これは単なる情報であり、Composeは実行時には最新のスキーマを用いるとのこと。むしろ記述すると、実態とズレが生じるので書かないことにした。
The top-level version property is defined by the Compose Specification for backward compatibility. It is only informative.
Compose doesn't use version to select an exact schema to validate the Compose file, but prefers the most recent schema when it's implemented.
出典:https://docs.docker.com/compose/compose-file/04-version-and-name/

bundleはディレクトリ内で管理する
bundle installの生成ファイルをどこで管理するか。ローカル環境であれば、bundle config set path vendor/bundle
などを用いて、そのプロジェクト内で管理する。一方でコンテナ環境であれば、グローバルにinstallしても良さそうである。
然乍、プロジェクト内で管理することにした。理由は、開発時にGemのソースコードを読むのはよくある為。そのディレクトリ内でコードを読めた方が何かと都合が良い。

vendor/bundleをバインドマウントから外す
以下のようにcompose.ymlを記述した。
app:
# 略
volumes:
- .:/app
# 略
このままだと問題が生じる。ホストのvendor/bundleがコンテナに同期されてしまう。例えば、ローカル環境(ruby2系)でbundle installして作成されたvendor/bundleがコンテナ(ruby3系)に同期されてしまうといった問題である。
こういう場合は、ボリュームでマウントを上書きする。コンテナはホストではなく、ボリュームを参照するようになる。
app:
# 略
volumes:
- .:/app
- $PWD/vendor/bundle
Volume Trickとも呼ばれる。

不要なファイルの同期を防ぐ
上記のVolume Trickは、高速化においても有用である。バインドマウントよりも、ボリュームの方がパフォーマンスは優れている。ホストのファイルで同期が不要なものもボリュームでマウントを上書きする。
app:
# 略
volumes:
- .:/app
- $PWD/vendor/bundle
- $PWD/tmp
- $PWD/log
- $PWD/.git

anonymous volumeは避ける
上記でマウントを上書きする為に、anonymous volumeを使用した。然乍、anonymous volumeはコンテナを立ち上げるために別のボリュームとして生成されるため、大量のボリュームが作成されてしまう。名前付きに変更する。
volumes:
mysql_data:
vendor_bundle:
tmp:
log:
git:
services:
web:
# 略
volumes:
- .:/tunag-education
- vendor_bundle:$PWD/vendor/bundle
- tmp:$PWD/tmp
- log:$PWD/log
- git:$PWD/.git

Railsコマンドが実行できない
コンテナを立ち上げる際に、/usr/local/bundleが見つからずエラーが発生する。ボリュームを作成して解消する。同期性は不要なので、cachedオプションを加えておく。
volumes:
bundle:
# 略
services:
web:
# 略
volumes:
- .:/tunag-education
- bundle:/usr/local/bundle:cached