Next.jsとRailsを活用したDocker環境構築
はじめに
React、TypeScript、Tailwind CSS (v4)、Rails、PostgreSQLを扱えるDocker環境を構築する時に、インストールするパッケージをフロントエンド用とバックエンド用のディレクトリに分け、効率的に管理できるようにしたいと思ったので、備忘録として記事にまとめてみました。
目標
フロントエンドのビルドツールにNext.jsを採用し、 React + TypeScript + Tailwind CSS (v4) + Rails + PostgreSQLを搭載したDocker環境の構築を目指します。
インストールするパッケージはフロントエンド用とバックエンド用でそれぞれ管理できるようにし、dbサービスを含めた計3つのコンテナを構築します。
frontend、backend、dbの3つのコンテナの構成を目指します
環境構築までのステップ
以下の3ステップを踏んでいき、Docker環境の構築を行います。
【STEP1】React+TypeScriptプロジェクトの生成
1. Create-next-appでフロントエンドプロジェクトを生成
2. TypeScript、Tailswind CSS、App Router(ルーティングシステム)、ESLintのインストール
【STEP2】Railsプロジェクトの生成
1. Rails newでRailsプロジェクトを生成
【STEP3】コンテナのビルド
1. compose.yml と Dockerfile.dev の作成
2. コンテナを構築&起動
【準備】作業ディレクトリの作成
作業用のディレクトリを作成します。
アプリ名など分かりやすい名前にしましょう。
$ mkdir myapp # ここでは作業ディレクトリ名を「myapp」とします
【STEP1】React+TypeScriptプロジェクト生成
手順1. create-next-appの実行
以下のコマンドを実行してください。
⚠️ --tailwindオプションについて
create-next-appで--tailwind
オプションを付加すると、Tailwind CSS v4がインストールされるようになったそうです。
v3を使う場合は--tailwind
オプションをつけず、手動でインストールをする必要があります。
# 一時的なNode.jsコンテナを起動してコンテナのシェルに接続
$ docker run --rm -it -v $(pwd)/front:/app -w /app node:22.16.0 sh
# yarn createで、next-appでプロジェクトを生成 (⚠️--tailwindオプションについて)
yarn create next-app . --typescript --tailwind --eslint --app --src-dir --turbopack --import-alias "@/*"
# package.jsonの設定
# エイリアスコマンド"dev"を"--hostname 0.0.0.0 --turbopack”として設定
sed -i 's/"dev": "next dev --turbopack"/"dev": "next dev --turbopack --hostname 0.0.0.0"/' package.json
# エイリアスコマンド"start"を"--hostname 0.0.0.0”として設定
sed -i 's/"start": "next start"/"start": "next start --hostname 0.0.0.0"/' package.json
# コンテナから退出
exit
📝 create-next-appのオプション説明
-
-typescript
: TypeScriptを使用 -
-tailwind
: Tailwind CSSを含める -
-eslint
: ESLintを設定 -
-app
: App Routerを使用(Next.js 13+の新機能であるルーティングシステム) -
-src-dir
: ソースコードの格納先となるsrcディレクトリを作成 -
-import-alias "@/*"
: インポートエイリアスを設定
モジュールをインポートする際に、相対パスを使わずに@を使ったエイリアスで使用できるようになります。
相対パスでの指定 :import Component from '../../../components/Component’
エイリアス@での指定:import Component from '@/components/Component’
📝 sed -i コマンドについて
-
sed
: ストリームエディタで、テキストの処理や変換を行うコマンド -
-i
: in-placeの略で、指定したファイルを直接編集するオプション
これを使うと、変更がそのままファイルに反映される -
's/ 文字列1 / 文字列2 /'
:s/ は置換コマンドで、文字列1を文字列2に置換します
例えば、s/[0-9]/X/g
と書いた場合、数字を全てX
に置き換えることができます
※/g
:グローバルの略で、検索ヒットした文字列「全て」を対象にとります
📝 --hostname 0.0.0.0”について
コンテナ内のアプリケーションを外部からアクセス可能にするための設定です。
Next.jsでは--host
ではなく、-- hostname
としないとエラーになります。
{
"name": "app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack --hostname 0.0.0.0", // ここが変更される
"build": "next build",
"start": "next start --hostname 0.0.0.0", // ここが変更される
"lint": "next lint"
},
"dependencies": {
"react": "^19.0.0",
"react-dom": "^19.0.0",
"next": "15.3.3"
},
"devDependencies": {
"typescript": "^5",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"@tailwindcss/postcss": "^4",
"tailwindcss": "^4",
"eslint": "^9",
"eslint-config-next": "15.3.3",
"@eslint/eslintrc": "^3"
}
}
myapp/frontディレクトリ下に、プロジェクトファイル群が生成され、package.jsonが画像のように記述されていればOKです。
手順2. next.config.ts設定の更新
next.config.tsファイルを開き、下記の内容で更新してください。
フロントエンドからのAPIリクエストを直接バックエンドに届くようにします。
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
experimental: {
// Docker環境でのファイル監視設定
},
async rewrites() {
return [
{
source: '/api/:path*',
destination: 'http://backend:3001/api/:path*', // Rails APIへのプロキシ
},
];
},
};
export default nextConfig;
【STEP2】Railsプロジェクトの生成
手順1. Rails newの実行
下記のコマンドは、一時的なbackendコンテナを起動し、コンテナ内でRailsのインストールとRailsプロジェクトを生成します。
$ docker run --rm -it -v $(pwd)/back:/app -w /app ruby:3.4.2 bash -c "gem install rails -v 7.2.2 && rails _7.2.2_ new . -d postgresql -j"
📝 Rails newのオプション
-d postgresql
:PostgreSQLデータベースを使用することを指定
-j
:JavaScriptを使用することを指定
📝 docker runのオプション
--rm
:コマンド実行の完了後、コンテナを破棄
-w
:コンテナ内の作業ディレクトリを指定
-i
:コンテナの標準入力(STDIN)をオープンにすることができ、コンテナの中にいる状態でコマンドを入力できるようになる。
-t
:仮想端末(TTY)を割り当てられ、コンテナ内での出力が確認できるようになる。
-it
:-iと-tを組み合わせたオプションで、コンテナ内でコマンドを入力したり、出力を確認したりできるようになる。
画像のように、backディレクトリ内にRailsプロジェクトができていたらOKです。
手順2. database.ymlの設定
config/database.yml
を以下のように追加修正してください
default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
host: db # 追加(※compose.ymlで定義したサービス名にすること!)
username: postgres # 追加
password: password # 追加
【STEP3】 コンテナのビルド
手順1. ファイルの作成
Dockerfile.dev と compose.yml を作成します。
Dockerfile.devはフロントエンド用とバックエンド用の2種類を作成し、各ディレクトリ下に配置します。
1-1. compose.ymlファイルの作成
myapp/下に作成します。
$ touch compose.yml
作成したcompose.ymlに、以下の内容をコピー&ペーストしてください。
version: '3.8'
services:
# PostgreSQLデータベース
db:
image: postgres:17
restart: always
environment:
TZ: Asia/Tokyo
POSTGRES_DB: myapp_development
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5431:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -d myapp_development -U postgres"]
interval: 10s
timeout: 5s
retries: 5
# Railsアプリケーション
backend:
build:
context: ./back
dockerfile: Dockerfile.dev
command: bash -c "bundle install && bundle exec rails db:prepare && rm -f tmp/pids/server.pid && bundle exec rails server -b 0.0.0.0"
tty: true
stdin_open: true
volumes:
- ./back:/back
- bundle_data:/usr/local/bundle:cached
ports:
- "3001:3000"
environment:
TZ: Asia/Tokyo
depends_on:
db:
condition: service_healthy
# React開発サーバー(Next.js)
frontend:
build:
context: ./front
dockerfile: Dockerfile.dev
command: bash -c "yarn run dev"
tty: true
stdin_open: true
volumes:
- ./front:/front
- node_modules_frontend:/front/node_modules
ports:
- "3000:3000" # Next.jsのデフォルトポートは3000
environment:
TZ: Asia/Tokyo
depends_on:
- backend
volumes:
postgres_data:
bundle_data:
node_modules_frontend:
📝 command: bash -c "yarn run dev" について
package.jsonのscripts
では、任意のシェルスクリプトをエイリアス設定できます。
{
// 省略
"scripts": {
// 任意のシェルスクリプトをエイリアス設定
"dev": "next dev --turbopack --hostname 0.0.0.0",
"build": "next build",
"start": "next start --hostname 0.0.0.0",
"lint": "next lint"
},
// 省略
よって、yarn run
コマンドでエイリアス”dev”を呼び出していることになるので、command: bash -c "yarn run dev”
は以下のシェルスクリプトを実行していることになります。
# next.jsサーバーを開発モードで起動させるコマンド
next dev --turbopack --hostname 0.0.0.0
📝 Volumesのマウントについて
ホストマシン側のディレクトリとコンテナ側のディレクトリのマウント設定を行うと、紐づけたディレクトリ同士のデータが同期状態となります。
マウントの設定の対象となったコンテナのディレクトリ内のデータは、コンテナを再起動してもデータが失われなくなります(=データの永続化)。
volumes:
- ./back:/back # myapp/back(ホストマシン側)を/back(コンテナ側)にマウント
1-2. front/Dockerfile.devファイルの作成
frontディレクトリ下に作成します
$ touch front/Dockerfile.dev
作成したDockerfile.devに、以下の内容をコピー&ペーストしてください。
# Node.jsのltsである22.16.0
FROM node:22.16.0
# 必要なパッケージをインストール
RUN apt-get update && apt-get install -y libc6-dev git && apt-get clean
# アプリケーションディレクトリを作成
WORKDIR /front
# package.jsonとyarn.lockをコピーしてyarn install
COPY ./package.json ./yarn.lock ./
RUN yarn install
# アプリケーションコードを.(/front/)にコピー
COPY . .
1-3. back/Dockerfile.devファイルの作成
backディレクトリ下に作成します
$ touch back/Dockerfile.dev
作成したDockerfile.devに、以下の内容をコピー&ペーストしてください。
# Ruby 3.4.2 のイメージを取得
FROM ruby:3.4.2
# 必要なパッケージをインストール
RUN apt-get update -qq && apt-get install -y \
postgresql-client \
build-essential \
libpq-dev \
imagemagick \
git \
&& rm -rf /var/lib/apt/lists/*
# アプリケーションディレクトリを作成
WORKDIR /back
# GemfileとGemfile.lockをコピーしてbundle install
COPY ./Gemfile ./Gemfile.lock ./
RUN bundle install
# アプリケーションコードを.(/back/)にコピー
COPY . .
手順2. ディレクトリ構成の確認
Dockerfile.devとcompose.ymlが以下のように配置されていることを確認してください。
myapp/
│
├── compose.yml
│
├── back/ # バックエンド(Rails)用フォルダ
│ └── Dockerfile.dev
│
└── front/ # フロントエンド用フォルダ
└── Dockerfile.dev
手順3. コンテナを起動
3つのコンテナを構築&起動していきます。
# コンテナイメージの作成 -> コンテナの構築 -> コンテナ起動までを一括で実行
$ docker compose up --build
📝 起動中のコンテナとイメージ、ボリューム、キャッシュを削除
# 起動中のコンテナ、イメージ、ボリュームを削除
$ docker compose down --volumes --remove-orphans
# キャッシュの削除
$ docker builder prune -f
※もしコンテナの再構築を行う場合、前のコンテナのキャッシュを削除しないままdocker compose up --build
を実行してしまうと、修正前のDockerfile.devをもとにコンテナイメージを構築してしまうので必ずキャッシュを削除すること!
手順4. アプリの起動の確認
それぞれのローカルホストのURLに飛んで、成功例と同じ画面が表示されたら成功です。
-
localhost:[フロントエンドのポート番号]
-
localhost:[バックエンドのポート番号]
まとめ
今回はフロントエンド用とバックエンド用のコンテナに分けてのDocker環境構築を行いました。
自分の検索能力が低いからか、記事を見つけることができなかったので、自分なりの構築手順でまとめてみました。
なるべく手間のかからない環境構築手順に仕上げたつもりなので、もし参考になりましたら幸いです。
Discussion