もふもふ技術部

IT技術系mofmofメディア

Rails7 + PostgreSQL + esbuild を docker-compose で環境構築する

Rails7がリリースされてから、環境構築で躓いた経験がある方は少なくないのではないでしょうか。
今回は、Rails7 + PostgreSQL + esbuild の環境を docker-compose で構築していきたいと思います。

Rails7 + PostgreSQL + importmap の環境構築については以下の記事をご参照ください。

www.mof-mof.co.jp

1. ファイルを準備する

まず始めに、以下の2つのファイルを作成します。

  • Dockerfile.dev
  • docker-compose.yml

Rails7.1から rails new で新規プロジェクトを作成したときに Dockerfile が自動生成されるようになりました。
そこで今回は、開発用のDockerfile は名前が競合しないように Dockerfile.dev と別名にしています。

次に、各ファイルの中身を以下のようにしていきます。

Dockerfile.dev

ポイント1
Dockerfile.dev の中ではRailsをインストールしません。Railsプロジェクト内には GemfileGemfile.lock があるはずなので、そちらを参照して正しいバージョンのRailsをインストールするべきです。

ポイント2
esbuild の環境にはnodeyarn が必要なので nodeのイメージをセットアップした後に、Rubyのイメージへ必要なファイルをコピーします。

FROM node:20.12.0-alpine as node

RUN apk add --no-cache bash curl && \
    curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 1.22.19

FROM ruby:3.3.0-alpine

COPY --from=node /usr/local/bin/node /usr/local/bin/node
COPY --from=node /usr/local/bin/npm /usr/local/bin/npm
COPY --from=node /usr/local/bin/npx /usr/local/bin/npx
COPY --from=node /opt/yarn-* /opt/yarn
RUN ln -fs /opt/yarn/bin/yarn /usr/local/bin/yarn
RUN apk add --no-cache git build-base libxml2-dev libxslt-dev postgresql-dev postgresql-client tzdata bash vim && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

ENV APP_ROOT /app
RUN mkdir $APP_ROOT
WORKDIR $APP_ROOT

ENV LANG=ja_JP.UTF-8 \
    BUNDLE_JOBS=4 \
    BUNDLE_RETRY=3 \
    EDITOR=vim
RUN gem update --system && \
    gem install --no-document bundler:2.5.7

RUN bundle config set force_ruby_platform true

docker-compose.yml

ポイント1
command の箇所で Railsサーバーを起動する前に bundle install を実行しています。もしGemfileに変更があったとしても、コンテナを起動する前にgemの変更点が適用されます。これでRailsサーバーを起動したときに「あ〜〜、bundle install忘れてた!!」という事件が起きにくくなるでしょう。

ポイント2
command の箇所で Railsサーバーを起動する前に yarn install を実行しています。もしpackage.jsonに変更があったとしても、コンテナを起動する前にpackage.jsonの変更点が適用されます。これでRailsサーバーを起動したときに「あ〜〜、yarn installも忘れてた!!」という事件が起きにくくなるでしょう。

ポイント3
/usr/local/bundle をvolumeにマウントすることにより、 bundle install で作成されたbundleデータが永続化されます。これにより、コンテナを起動するたびに「bundle install めっちゃ長いな〜〜」という待ち時間を削減できるでしょう。

ポイント4
/app/node_modules をvolumeにマウントすることにより、 yarn install で作成されたnode_modulesのデータが永続化されます。これにより、コンテナを起動するたびに「yarn install めっちゃ長いな〜〜」という待ち時間を削減できるでしょう。

version: '3'
services:
  app:
    build:
      context: .
      dockerfile: "Dockerfile.dev"
    stdin_open: true
    tty: true
    ports:
      - 3000:3000
    command: /bin/sh -c "bundle install && yarn install && rm -f tmp/pids/server.pid && bin/dev"
    environment:
      DB_USER: postgres
      DB_PASS: postgres
      DB_HOST: postgres
      DB_PORT: 5432
    depends_on:
      - postgres
    volumes:
      - .:/app:delegated
      - node-modules:/app/node_modules:delegated
      - bundle-data:/usr/local/bundle:delegated

  postgres:
    image: postgres:16.2
    stdin_open: true
    tty: true
    restart: always
    ports:
      - 5432:5432
    environment:
      PGDATA: /var/lib/postgresql/data/pgdata
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      TZ: Asia/Tokyo
    volumes:
      - pgsql-data:/var/lib/postgresql/data:cached

volumes:
  pgsql-data:
  bundle-data:
  node-modules:

2. 環境構築をする

ファイルの準備ができたら、各種コマンドを実行していきます。
今回は、新規Railsプロジェクトを作成してみます。

  1. docker compose build を実行します。
  2. docker compose run --rm app gem install rails を実行します。
    最新のRailsがインストールされます。
  3. docker compose run --rm app rails new . -d postgresql -j esbuild を実行します。
    DBにPostgreSQLを使用しますよというオプションと、ビルドはesbuildを使用しますよというオプションをつけます。
    このまま実行するとアプリの名前が App になるので、変えたい場合は -n アプリの名前 のオプションを追加します。
  4. config/database.ymldefault 内に以下を追記します。

     username: <%= ENV['DB_USER'] %>
     password: <%= ENV['DB_PASS'] %>
     host: <%= ENV['DB_HOST'] %>
    
  5. package.json に以下の内容を追記します。

     ,
       "scripts": {
         "build:js": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds",
         "build": "yarn build:js"
       }
    
  6. Procfile.dev を以下のように修正します。

     web: bin/rails server -b 0.0.0.0 -p 3000
     js: yarn build:js --watch
    
  7. docker compose up postgres -d を実行します。
    DBを作成するために、postgresコンテナだけ立ち上げます。
  8. docker compose run --rm app rails db:create を実行します。
    これでdevelopment用とtest用のDBが作成されました。
  9. docker compose stop postgres を実行します。
    postgresコンテナが停止します。
  10. docker compose up を実行します。
    Railsサーバーを起動しています。
  11. http://localhost:3000/ にアクセスしてページが表示されれば完了です。
    rails newした時によくみる画面

Procfile.devが追加され、Railsサーバーの起動方法が今までと異なっていることが Rails7の環境構築でよくある躓きポイントではないでしょうか?

ポイント1
CSSのコンパイルが必要になった時のために build:jsbuild に分けています。また、Herokuなどにデプロイした時は build のscriptが実行されるため build も用意しています。具体的な使い方はポイント2に記載しています。

ポイント2
CSSのコンパイルが必要になった場合は package.json"scripts" を追加しましょう。そして、追加したscriptsを実行できるように Procfile.dev にも追記をするのを忘れずに!

以下が、tailwind を使った例です。

package.json

"scripts": {
  "build:js": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds",
  "build:css": "tailwindcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css",
  "build": "yarn build:js && yarn build:css"
}

Procfile.dev

web: bin/rails server -b 0.0.0.0 -p 3000
js: yarn build:js --watch
css: yarn build:css --watch

最後に

これでRails7の環境構築ができました!
ボイラープレートをGitHubで公開していますので是非ご活用ください!!

github.com