Dockerを使用したRubyOnRailsとNext.jsの開発環境構築ガイド

# はじめに

Webアプリケーションの開発環境を構築する際に、Dockerを使用することは効果的な方法の1つです。特に、Rails APIモードとNext.jsを組み合わせて開発する場合、Dockerを利用することで環境の構築と管理を簡素化できます。この記事では、Dockerを使用してRails APIモードとNext.jsの開発環境を構築する手順を紹介します。

# 技術スタックの概要

### Rails APIモード
RailsのAPIモードは、フロントエンドとバックエンドを分離して開発する場合に便利な機能です。APIモードを使用することで、データの提供と処理を行うバックエンドのみを構築できます

### Next.js
Next.jsは、Reactアプリケーションの開発をサポートするフレームワークです。サーバーサイドレンダリングや静的サイト生成などの機能を提供し、パフォーマンスの向上やSEO対策に役立ちます

### Docker
Dockerは、コンテナ仮想化技術を使用してアプリケーションを環境に依存せずに実行することができるツールです。開発、テスト、本番環境など、異なる環境でアプリケーションを一貫して動作させることが可能です

# 手順

メインリポジトリの作成とサブモジュール化から始まり、Dockerの設定、そしてフロントエンドとバックエンドの環境構築までの流れを説明します。

### 1.メインリポジトリの作成とサブモジュール化:

GitHubでメインリポジトリを作成します。このリポジトリには、フロントエンドとバックエンドのサブモジュールが含まれます。
メインリポジトリ内に、フロントエンドとバックエンドのディレクトリをサブモジュールとして追加します。
```
(base) dev % cd TeachChest 
(base) TeachChest % git init
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint: 
hint: 	git config --global init.defaultBranch <name>
hint: 
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint: 
hint: 	git branch -m <name>
Initialized empty Git repository in /Users/jima/dev/TeachChest/.git/

(base) TeachChest % echo "# TeachChest" >> README.md
(base) TeachChest % git add README.md
(base) TeachChest % git commit -m "first commit"
[master (root-commit) d0e6835] first commit
 1 file changed, 1 insertion(+)
 create mode 100644 README.md
 
(base) TeachChest % git branch -M main
(base) TeachChest % git remote add origin git@github.com:jijimama/TeachChest.git
(base) TeachChest % git push -u origin main
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 223 bytes | 223.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To github.com:jijimama/TeachChest.git
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.
```
サブモジュールの設定
```
(base) TeachChest % git submodule add git@github.com:jijimama/TeachChest-front.git front
Cloning into '/Users/jima/dev/TeachChest/front'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.

(base) TeachChest % git submodule add git@github.com:jijimama/TeachChest-back.git back  
Cloning into '/Users/jima/dev/TeachChest/back'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.

(base) TeachChest % git add .
(base) TeachChest % git commit -m "Add: submolues"
[main e7f132a] Add: submolues
 3 files changed, 8 insertions(+)
 create mode 100644 .gitmodules
 create mode 160000 back
 create mode 160000 front
 
(base) TeachChest % git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 434 bytes | 434.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To github.com:jijimama/TeachChest.git
   d0e6835..e7f132a  main -> main

(base) TeachChest % ls -al
total 24
drwxr-xr-x   8 jima  staff  256  5 12 13:14 .
drwxr-xr-x  14 jima  staff  448  5 12 13:09 ..
drwxr-xr-x  13 jima  staff  416  5 12 13:12 .git
-rw-r--r--   1 jima  staff  169  5 12 13:12 .gitmodules
-rw-r--r--   1 jima  staff   13  5 12 13:09 README.md
drwxr-xr-x   5 jima  staff  160  5 12 13:15 back
-rw-r--r--@  1 jima  staff  778  5 12 13:14 docker-compose.yml
drwxr-xr-x   5 jima  staff  160  5 12 13:14 front
```

### 2.Dockerの設定

メインリポジトリ内にDockerfileとdocker-compose.ymlを作成します。
Dockerfileには、フロントエンドとバックエンドそれぞれの環境構築手順を記述します。
docker-compose.ymlには、フロントエンドとバックエンドのコンテナの設定を記述します。

```yml
version: "3"
services:
  db:
    image: postgres:15.5
    environment:
      POSTGRES_DB: app_development
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
  back:
    build:
      context: ./back
      dockerfile: Dockerfile
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -b '0.0.0.0'"
    volumes:
      - ./back:/app
    ports:
      - "3000:3000"
    depends_on:
      - db
    tty: true
    stdin_open: true
    environment:
      - RAILS_ENV=development
  front:
    build:
      context: ./front/
      dockerfile: Dockerfile
    volumes:
      - ./front:/app
    command: yarn dev -p 4000
    ports:
      - "8000:4000"
volumes:
  postgres_data:
```

### 3.フロントエンドの環境構築（Next.js）

フロントエンドのディレクトリに移動し、Next.jsプロジェクトを作成します。
必要なパッケージをインストールし、開発環境を構築します。
Dockerfile内で、フロントエンドのビルドと実行のための設定を追加します。
```dockerfile
FROM node:19.4.0
WORKDIR /app
```


### 4.バックエンドの環境構築（Rails API）:

バックエンドのディレクトリに移動し、Rails APIモードのプロジェクトを作成します。
必要なgemをインストールし、データベースのセットアップを行います。
Dockerfile内で、バックエンドのビルドと実行のための設定を追加します。
```dockerfile
FROM ruby:3.2.2
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client

WORKDIR /app

COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock

RUN gem install bundler
RUN bundle install

COPY . /app

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

EXPOSE 3002

CMD ["rails", "server", "-b", "0.0.0.0"]
```
また、entrypoint.shを作成します。entrypoint.shは、コンテナが開始された時に実行されるスクリプトです。
```sh
#!/bin/bash
set -e

rm -f /app/tmp/pids/server.pid

exec "$@"
```
$docker-compose buildをする前に、backディレクトリにGemfileとGemfile.lockを作成します。Gemfile.lockは空で問題ありません。

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

ruby "3.2.2"

gem "rails", "~> 7.0.5"

```
ルートディレクトリに移動

```
(base) TeachChest % docker-compose build
[+] Building 61.5s (21/21) FINISHED                                                                                                                                                    docker:desktop-linux
 => [back internal] load build definition from Dockerfile                                                                                                                                              0.0s
 => => transferring dockerfile: 445B                                                                                                                                                                   0.0s
 => [front internal] load build definition from Dockerfile                                                                                                                                             0.0s
 => => transferring dockerfile: 103B                                                                                                                                                                   0.0s
 => [back internal] load metadata for docker.io/library/ruby:3.2.2                                                                                                                                     2.4s
 => [front internal] load metadata for docker.io/library/node:19.4.0                                                                                                                                   2.6s
 => [back internal] load .dockerignore         
 ・・・・

 (base) TeachChest % docker images
REPOSITORY                     TAG       IMAGE ID       CREATED          SIZE
teachchest-back                latest    e08b29de2a5b   12 seconds ago   1.15GB
teachchest-front               latest    e9d09eec03a5   23 seconds ago   948MB
```
### 5.環境構築
フロントエンド側をやっていきます。frontディレクトリへ移動。
```
(base) front % docker-compose run --rm front yarn create next-app .
[+] Creating 2/0
 ✔ Network teachchest_default         Created                                                                                                                                                          0.0s 
 ✔ Volume "teachchest_postgres_data"  Created                                                                                                                                                          0.0s 
yarn create v1.22.19
・・・・

(base) front % docker-compose up front
[+] Running 1/0
 ✔ Container teachchest-front-1  Created                                                                                                                                                               0.0s 
Attaching to front-1
front-1  | yarn run v1.22.19
```
次にバックエンド。
```
(base) back % docker-compose run --rm --no-deps back bundle exec rails new . --api --database=postgresql
(base) back % docker-compose run --rm back bundle install
[+] Running 15/15
 ✔ db 14 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿]      0B/0B      Pulled                                                                                                                                               17.6s 
   ✔ 25d3892798f8 Pull complete                                                                                                                                                                        3.6s 
   ✔ 77c2305dd978 Pull complete                                                                                                                                                                        0.7s 
   ✔ 54c99c28f11f Pull complete                                                                                                                                                                        1.1s 
   ✔ 5feeada49781 Pull complete

(base) back % docker-compose run --rm back rails db:create

(base) back % docker-compose up
[+] Running 3/0
 ✔ Container teachchest-db-1     Running                                                                                                                                                               0.0s 
 ✔ Container teachchest-front-1  Created                                                                                                                                                               0.0s 
 ✔ Container teachchest-back-1   Created                                                                                                                                                               0.0s 
```

以上で、環境構築完了です。最後までお読みいただきありがとうございました。