行動すれば次の現実

テック中心の個人ブログ

Next.jsとRails APIのMonorepo管理とDockerを使った開発環境構築

フロントエンドにNext.js、バックエンドにRailsのAPIモードを採用した構成において、一つのリポジトリで管理するMonorepoの環境をDockerを利用して開発環境を構築する方法について解説します。

環境情報

  • Next.js 13.4.7
  • Rails 7.0.5
  • Postgresql 15.3
  • Docker 20.10.12
  • docker-compose 1.29.2

セットアップ前のProcjectの構成

.
├── front
       ├── Dockerfile
├── api
       ├── Dockerfile
       ├── Gemfile
       ├── Gemfile.lock # 空ファイル
       ├── entrypoint.sh 
├── docker-compose.yml

docker-compose.ymlの定義

version: "3.9"
services:
  front:
    build:
      context: ./front/
      dockerfile: Dockerfile
    volumes:
      - ./front/app:/usr/src/app
    command: 'yarn dev'
    ports:
      - "8000:3000"
  api:
    tty: true
    build:
      context: ./api/
      dockerfile: Dockerfile
    ports:
      - 3000:3000
    volumes:
      - ./api:/app
      - bundle:/usr/local/bundle
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    depends_on:
      - db
  db:
    image: postgres:15.3
    volumes:
      - postgres:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: myapp
      POSTGRES_PASSWORD: password
      POSTGRES_DB: app_development
      TZ: "Asia/Tokyo"
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=C"
volumes:
  bundle:
  postgres:

front/Dockerfileの定義

FROM node:20.3.1
ENV TZ Asia/Tokyo
WORKDIR /usr/src/app

api/Dockerfileの定義

FROM ruby:3.2.2
ENV LANG=C.UTF-8 \
  TZ=Asia/Tokyo
WORKDIR /app
RUN apt-get update -qq && apt-get install -y postgresql-client

COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock

RUN bundle install

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]

CMD ["rails", "server", "-b", "0.0.0.0"]

api/Gemfileの定義

source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby "3.2.2"

gem "rails", "~> 7.0.5"

api/entrypoint.shの定義

#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

front環境の構築

cd front
# next.jsのセットアップ
docker-compose run --rm front yarn create next-app .
# frontサービスのみ起動
docker-compose up front

http://localhost:8000/ にアクセスして下記のようなウェルカム画面が出力されれば完了です。

api環境の構築

cd api
# Railsのセットアップ
docker-compose run --rm --no-deps api bundle exec rails new . --api --database=postgresql

国際化とタイムゾーンの設定

日本をベースにしたサービスの場合、下記を追加しておきます。

config/application.rb

module App
  class Application < Rails::Application
    config.load_defaults 7.0
    config.api_only = true
    # 下記を追加
    config.time_zone = 'Tokyo'
    config.active_record.default_timezone = :local
    config.i18n.default_locale = :ja
  end
end

ホスト許可の設定

development.rbに以下の設定を追加します。これを追加することでapiホストからのリクエストができるようになります。

config/environments/development.rb

Rails.application.configure do
・・・
  config.hosts << "api"
end

データベースセットアップ

セットアップが完了したら設定ファイルをconfig/database.ymlを以下のように書き換えます。

api/config/database.yml

default: &default
  adapter: postgresql
  encoding: utf8
  host: db
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: myapp
  password: password

development:
  <<: *default
  database: app_development

test:
  <<: *default
  database: app_test

production:
  <<: *default
  database: app_production
  username: myapp
  password: <%= ENV["APP_DATABASE_PASSWORD"] %>

その後、データベースを構築して、起動確認を行います。

docker-compose run --rm api rails db:create
docker-compose up

frontは http://localhost:8000/ でNext.jsの画面が出力され、apiは http://localhost:3000/ で下記のような画面が出力されれば作業は完了です。

セットアップ後のProcjectの構成

バージョンによって違いはあるかもしれませんが、最終的にはプロジェクトは以下のような構成になります。