📚
Next.js + Rails (APIモード)アプリケーションの環境構築
はじめに
フロントエンドがNext.js、バックエンドがRuby on RailsのAPIモードで構成するアプリケーションの開発環境をまとめました。
バックエンドはDockerを使用して環境を統一し、依存関係の管理やデプロイを容易にしています。
モノレポでの管理やCI/CDでフロントエンド・バックエンドで個別のワークフローを実行できるようにもしています。
技術スタック
バックエンド
- Ruby: 3.2.2
- Ruby on Rails: 8.0.1(API モード)
- PostgreSQL: 14
- Redis: 7
- Sidekiq: バックグラウンドジョブ処理
フロントエンド
- Next.js(App Router)
- TypeScript: ^5.0.0
- Node.js: ^20.0.0
- TailwindCSS
- Zustand(状態管理)
- Jest + React Testing Library
インフラストラクチャ
- Docker & Docker Compose
- GitHub Actions(CI/CD)
プロジェクト構成
本プロジェクトはモノレポ(単一リポジトリ)で管理されており、以下のような構成となっています:
my-app/
├── .github/
│ └── workflows/ # GitHub Actions設定
│ ├── frontend.yml # フロントエンド用CI/CD
│ └── backend.yml # バックエンド用CI/CD
├── frontend/ # Next.jsアプリケーション
└── backend/ # Rails APIアプリケーション
モノレポ構成のメリット
-
コードの一元管理
- フロントエンド・バックエンドの変更履歴を一箇所で管理
- 依存関係の管理が容易
- デプロイの同期が取りやすい
-
開発効率の向上
- プロジェクト全体を一度にクローン可能
- 横断的な変更が容易
- チーム間の連携がスムーズ
-
CI/CD の柔軟な制御
- フロントエンド・バックエンドで個別のワークフローを実行可能
- 変更があった部分のみビルド・テストを実行
開発環境のセットアップ
前提条件
- Docker
- Docker Compose
- Git
1. プロジェクトのセットアップ
Dockerfile の作成
backend/Dockerfile.dev
を作成:
ARG RUBY_VERSION=3.2.2
FROM docker.io/library/ruby:$RUBY_VERSION-slim
# 必要なパッケージをインストール
RUN apt-get update -qq && apt-get install -y \
build-essential \
libpq-dev \
postgresql-client
# アプリケーションディレクトリを作成
WORKDIR /app
# Gemfile と Gemfile.lock をコピーし、依存関係をインストール
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
# アプリケーションの全ファイルをコンテナ内にコピー
COPY . /app
# サーバー起動
CMD ["rails", "server", "-b", "0.0.0.0"]
Docker Compose の設定
backend/docker-compose.yml
を作成:
version: "3"
services:
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/rails
- ruby-bundle-cache:/bundle
ports:
- "3000:3000"
environment:
RAILS_ENV: development
DATABASE_HOST: db
DATABASE_USERNAME: postgres
DATABASE_PASSWORD: postgres
depends_on:
- db
- redis
db:
image: postgres:14
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- "5432:5432"
redis:
image: redis:7
ports:
- "6379:6379"
sidekiq:
build: .
command: bundle exec sidekiq
volumes:
- .:/rails
- ruby-bundle-cache:/bundle
environment:
RAILS_ENV: development
DATABASE_HOST: db
DATABASE_USERNAME: postgres
DATABASE_PASSWORD: postgres
depends_on:
- db
- redis
volumes:
postgres_data:
ruby-bundle-cache:
external: true
2. データベース設定
backend/config/database.yml
を設定:
default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
host: <%= ENV.fetch("DATABASE_HOST") { "db" } %>
username: <%= ENV.fetch("DATABASE_USERNAME") { "postgres" } %>
password: <%= ENV.fetch("DATABASE_PASSWORD") { "postgres" } %>
development:
<<: *default
database: focus_forge_development
test:
<<: *default
database: focus_forge_test
production:
primary: &primary_production
<<: *default
database: app_production
username: app
password: <%= ENV["APP_DATABASE_PASSWORD"] %>
cache:
<<: *primary_production
database: app_production_cache
migrations_paths: db/cache_migrate
queue:
<<: *primary_production
database: app_production_queue
migrations_paths: db/queue_migrate
cable:
<<: *primary_production
database: app_production_cable
migrations_paths: db/cable_migrate
3. Gemfile の設定
backend/Gemfile
の主要な依存関係:
source "https://rubygems.org"
gem "rails", "~> 8.0.1"
gem "pg", "~> 1.1"
gem "puma", ">= 5.0"
gem "tzinfo-data", platforms: %i[ windows jruby ]
gem "bootsnap", require: false
gem "solid_cache"
gem "solid_queue"
gem "solid_cable"
gem "kamal", require: false
gem "thruster", require: false
group :development, :test do
gem "debug", platforms: %i[ mri windows ], require: "debug/prelude"
gem "brakeman", require: false
gem "rubocop-rails-omakase", require: false
end
4. アプリケーションの起動
# Dockerイメージのビルド
docker compose build
# コンテナの起動
docker compose up -d
# データベースの作成とマイグレーション
docker compose exec web rails db:create db:migrate
localhost:3000 にアクセスでこの画面が出れば完了です。
4. フロントエンド環境のセットアップ
4.1 Next.js プロジェクトの作成
# プロジェクトの作成
npx create-next-app@latest frontend
cd frontend
# 以下の質問に対して回答
✔ Would you like to use TypeScript? Yes
✔ Would you like to use ESLint? Yes
✔ Would you like to use Tailwind CSS? Yes
✔ Would you like to use `src/` directory? Yes
✔ Would you like to use App Router? (recommended) Yes
✔ Would you like to customize the default import alias (@/*)? Yes
4.2 依存関係のインストール
npm install
4.3 ESLint の設定
.eslintrc.json
を作成:
{
"extends": ["next/core-web-vitals"],
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/no-unused-vars": [
"error",
{ "argsIgnorePattern": "^_" }
],
"@typescript-eslint/no-explicit-any": "error",
"no-console": ["warn", { "allow": ["warn", "error"] }]
}
}
4.4 TypeScript の設定
tsconfig.json
を更新:
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
"**/*.mjs",
".next/types/**/*.ts"
],
"exclude": ["node_modules"]
}
4.5 開発サーバーの起動
# 開発サーバーの起動
npm run dev
localhost:3001 にアクセスでこの画面が出れば完了です。
4.6 ビルドとテスト
# 型チェック
npm run type-check
# リントチェック
npm run lint
# ビルド
npm run build
# プロダクションモードでの起動
npm run start
トラブルシューティング
バックエンド(Rails)
docker compose up
でポート 3000 が使用中のエラー
1. Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:3000 -> 0.0.0.0:0: listen tcp 0.0.0.0:3000: bind: address already in use
解決方法:
- 実行中のコンテナを確認
docker ps
- 該当のポートを使用しているコンテナを停止
docker stop [CONTAINER_ID]
web
サービスが見つからないエラー
2. Error response from daemon: service 'web' is not running container
解決方法:
- コンテナの状態を確認
docker compose ps
- サービスを再起動
docker compose down
docker compose up -d
フロントエンド(Next.js)
1. ESLint の設定の競合
Plugin "react-hooks" was conflicted between ".eslintrc.json » plugin:react-hooks/recommended" and ".eslintrc.json » eslint-config-next/core-web-vitals"
解決方法:
.eslintrc.json
を以下のように簡素化:
{
"extends": ["next/core-web-vitals"],
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/no-unused-vars": [
"error",
{ "argsIgnorePattern": "^_" }
],
"@typescript-eslint/no-explicit-any": "error",
"no-console": ["warn", { "allow": ["warn", "error"] }]
}
}
2. TypeScript の設定で Next.js の型定義が見つからないエラー
We detected TypeScript in your project and reconfigured your tsconfig.json file
解決方法:
tsconfig.json
のinclude
に.next/types/**/*.ts
を追加:
{
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
"**/*.mjs",
".next/types/**/*.ts"
]
}
共通のトラブルシューティング手順
- ログの確認
# Dockerコンテナのログ
docker compose logs -f [SERVICE_NAME]
# Next.jsの開発サーバーログ
npm run dev
- 依存関係の更新
# Railsの依存関係
bundle update
# Next.jsの依存関係
npm update
- キャッシュのクリア
# Dockerのキャッシュクリア
docker compose down
docker system prune -f
# Next.jsのキャッシュクリア
rm -rf .next
npm clean-install
- 設定ファイルの検証
-
docker-compose.yml
の環境変数が正しく設定されているか確認 -
.env
ファイルが適切に配置されているか確認 - 各種設定ファイル(
tsconfig.json
,.eslintrc.json
など)の構文エラーがないか確認
さいごに
以上が環境構築になります。
ぜひテンプレートリポジトリを使ってみてうまくいったよという方は
この記事にいいねとテンプレートリポジトリのほうにStar付けていただけるとうれしいです!
もしうまくいかなかったという方がいればコメントいただけると幸いです。
Discussion