Next.js14＋Rails7.1 APIモードをDockerで構築する手順

## 概要
フロントエンドにReact,Next.js、バックエンドにRuby on Rails(apiモード)を使用したアプリをDokerを用いて構築する際に、Rails7.1での変更が影響し構築時に時間を取られたので、備忘録を兼ねて構築手順を記載します。

以下のような方に役立つ手順となっていれば幸いです。
- Dockerを使用してRails7.1（apimモード）のアプリを構築したい方
- Dockerを使用してフロント（React,Next.js）とバックエンド（Rails）を分けてアプリ構築したい方

## 環境
アプリ構築時の環境は以下の通りです。執筆時点で可能な限り最新バージョンを使用するようにしました。
- Ruby： 3.3.1
- Rails： ~> 7.1.0
- mysql： 8.0
- node.js： 20.12.12

## 全体の流れ
以下の項目に沿って手順を記載します。
1. ディレクトリ構成とファイルの準備
1. フロントエンド側の環境構築
1. バックエンド側の環境構築

## １.ディレクトリ構成とファイルの準備
以下のディレクトリ構成になるようにディレクトリおよびファイル作成を行います。
```
.
├── api
│   ├── Dockerfile
│   ├── Gemfile
│   ├── Gemfile.lock
├── docker-compose.yml
└── front
    └── Dockerfile
```

```
作業する任意のディレクトリに移動し、下記のコマンドを実行します。
$ mkdir {api,front}
$ cd api
$ touch {Dockerfile,Gemfile,Gemfile.lock}
$ cd ..
$ cd front
$ touch Dockerfile
$ cd ..
$ touch docker-compose.yml
```

api/Dockerfile<br>
```Dockerfile
FROM ruby:3.3.1

ENV LANG=C.UTF-8 \
  TZ=Asia/Tokyo
RUN apt-get update -qq && apt-get install -y nodejs yarn
RUN mkdir /api
WORKDIR /api
COPY Gemfile Gemfile.lock /api/
RUN bundle install
```

api/Gemfile<br>
```Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 7.1.0'
```
api/Gemfile.lockはファイル作成のみで中身は空<br>

作業ディレクトリ直下のdocker-compose.yml<br>
```docker-compose.yml
services:
  db:
    image: mysql:8.0
    command: --default-authentication-plugin=mysql_native_password
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - 4306:3306
    volumes:
      - mysql-data:/var/lib/mysql
  api:
    build:
      context: ./api
    ports:
      - 3001:3001
    volumes:
      - ./api:/api
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3001 -b '0.0.0.0'"
    tty: true
    depends_on:
      - db
  front:
    build:
      context: ./front
    volumes:
      - ./front/app:/front
    command: 'yarn dev'
    ports:
      - 3000:3000
volumes:
  mysql-data:
```
front/Dokcerfile
```Dockerfile
FROM node:20.12.2
RUN mkdir /front
WORKDIR /front
```
各ファイルの編集完了後に下記コマンドを実行します。
```
$ docker compose build
```

## 2.フロントエンド側の環境構築
続いて、下記のコマンドを実行してフロントエンド側のアプリ構築を行います。
```
$ docker compose run --rm front yarn create next-app .
```
下記のような質問が聞かれるため、お好みで設定してください。
```
✔ Would you like to use TypeScript with this project? … No / Yes
✔ Would you like to use ESLint with this project? … No / Yes
✔ Would you like to use Tailwind CSS with this project? … No / Yes
✔ Would you like to use `src/` directory with this project? … No / Yes
✔ Use App Router (recommended)? … No / Yes
✔ Would you like to customize the default import alias? … No / Yes

```
アプリの生成が完了したら、起動して動作するか確認するため、下記コマンドを実行します。
```
$ docker compose up front
```
localhost:3000にアクセスしてNext.jsの初期画面が表示されると成功です。

## 3.バックエンド側の環境構築
最後に、バックエンド側のアプリ構築を行います。
Rails7.1ではアプリ生成時にDockerfileが自動生成されるため、当該ファイルを使用する場合としない場合で手順を記載します。
#### 自動生成されるDockerfileを使用する場合
下記コマンドを実行します。
```
$ docker compose run --rm api rails new . --force --api -d mysql
```

アプリ生成後に更新されたapi/Dockerfileを下記の通りに編集します。
```
//省略//
ENV RAILS_ENV="development" \
    BUNDLE_DEPLOYMENT="1" \
    BUNDLE_PATH="/usr/local/bundle"
//省略//
```

#### 自動生成されるDockerfileを使用しない場合
下記コマンドを実行します。
```
$ docker compose run --rm api rails new . --force --api -d mysql --skip-docker
```

以降は自動生成されるDockerfile使用・不使用に関わらず同様の手順です。
api/config/database.ymlを下記の通りに修正します。
```database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password　←修正箇所
  host: db　←修正箇所
```
修正後に下記コマンドを順番に実行します。
```
$ docker compose build
```

```
$ docker compose up
```

```
$ docker compose run api bin/rails db:create
```
データベース作成後、localhost:3001にアクセスしてRuby on Railsの初期画面が表示されると成功です。


## 参考情報
この記事は以下の情報を参考にして執筆しました。
[Next.js + Ruby on Rails(APIモード) on Docker 構築手順](https://zenn.dev/taku1115/articles/6c9fa97ab37e38)
[【Rails7 × Next.js】Dockerで環境構築してみる。](https://qiita.com/ippei_jp/items/1163a40a86d07fa691b2)
[rails7.1で生成されるDockerfileを覗いてみる](https://zenn.dev/youfuku/articles/a781e0b39be76c)