🥑

Next.js x Typescript x Docker x Rails APIの環境構築まで

2023/04/02に公開

技術スタック

  • Typescript
  • ESLint
  • Husky
  • storybook
  • React
  • Next.js
  • Docker
  • Ruby
  • Ruby on Rails
  • rspec

フロントエンド

gitリポジトリの作成

Github上でフロントエンド用のリポジトリを作成し、
sshでローカルにリポジトリをクローンしてきます。

cd /Workspace/sun_sun_gold
git clone git@github.com:iizukamaiko/sunsungold_frontend.git

空のsunsungold_frontendディレクトリが出来上がりました。

Next.jsアプリケーションの作成

クローンした際に出来たディレクトリに移動します。

cd /Workspace/sun_sun_gold/sunsungold_frontend

以下コマンドでアプリケーションを作成します。
(コマンドに.を追記することで、現在のディレクトリに中身が作成されます。)

yarn create next-app . --typescript

途中でESLintを使うか聞かれるので、YESを選択。

yarn create v1.22.17
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Installed "create-next-app@13.1.1" with binaries:
      - create-next-app
✔ Would you like to use ESLint with this project? … No / Yes // YESの選択状態でエンター



以下のようなディレクトリ群が出来上がりました。
(node_modulesディレクトリ配下のファイルは省略)

.
├── node_modules
├── pages
│   ├── api
│   │   └── hello.ts
│   ├── _app.tsx
│   ├── _document.tsx
│   └── index.tsx
├── public
│   ├── favicon.ico
│   ├── next.svg
│   ├── thirteen.svg
│   └── vercel.svg
├── styles
│   ├── globals.css
│   └── Home.module.css
├── .eslintrc.json
├── .gitignore
├── next-env.d.ts
├── next.config.js
├── package.json
├── README.md
├── tsconfig.json
└── yarn.lock

Huskyの導入

以下コマンドで、Huskyを追加します。
※linterかけ忘れ防止のため導入することにしました。

npx husky-init && yarn

各ファイルにHuskyの情報が追記されます。

package.json

  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",  // 追加
    "prepare": "husky install"  // 追加
  },
  
  ...
  
  "devDependencies": {
    "husky": "^8.0.0"  // 追加
  }

yarn.lock

// 追加
husky@^8.0.2:
  version "8.0.2"
  resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.2.tgz#5816a60db02650f1f22c8b69b928fd6bcd77a236"
  integrity sha512-Tkv80jtvbnkK3mYWxPZePGFpQ/tT3HNSs/sasF9P2YfkMezDl3ON37YN6jUUI4eTg5LcyVynlb6r4eyvOmspvg==

また、huskyディレクトリがroot直下に追加されます。
huskyディレクトリ配下は以下のようになっています。

.husky
├── _
│   ├── .gitignore
│   └── husky.sh
└── pre-commit

pre-commitファイルを編集します。
今回はyarnを使っているので、npm testyarn lintに修正します。

pre-commit

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

+ yarn lint

参照:https://typicode.github.io/husky/#/?id=automatic-recommended

Storybookの導入

以下コマンドでstorybookを導入します。

npx sb init --builder webpack5

途中でESLint pluginを導入するか聞かれるので、YESを選択します。

✔ Do you want to run the 'eslintPlugin' migration on your project? … (y/n) <- yを選択

root直下に.storybookディレクトリとstoriesディレクトリが作成されます。

.
├──.storybook
│   ├── main.js
│   └── preview.js
└── stories
    ├── assets
    ├── button.css
    ├── Button.stories.tsx
    ├── Button.tsx
    ├── header.css
    ├── Header.stories.tsx
    ├── Header.tsx
    ├── Introduction.stories.mdx
    ├── page.css
    ├── Page.stories.tsx
    └── Page.tsx

参照:https://storybook.js.org/blog/get-started-with-storybook-and-next-js/

OpenAPIの導入

OpenAPIに則ってAPIを定義し、そこからAPIクライアントを自動生成しようと思っています。
APIクライアント生成のためのopenapi-generator-cliを導入します。

yarn add @openapitools/openapi-generator-cli -D

openapi-generator-cliが追加されました。

package.json

"devDependencies": {
    "@babel/core": "^7.20.7",
    "@openapitools/openapi-generator-cli": "^2.5.2", // 追加された
    "@storybook/addon-actions": "^6.5.15",
    "@storybook/addon-essentials": "^6.5.15",
    "@storybook/addon-interactions": "^6.5.15",
    "@storybook/addon-links": "^6.5.15",
    "@storybook/builder-webpack5": "^6.5.15",
    "@storybook/manager-webpack5": "^6.5.15",
    "@storybook/react": "^6.5.15",
    "@storybook/testing-library": "^0.0.13",
    "babel-loader": "^8.3.0",
    "eslint-plugin-storybook": "^0.6.8",
    "husky": "^8.0.0"
  }

裏側では、nestjsが追加されました。
TODO: なぜ?これは調べる

yarn.lock

"@nestjs/common@8.4.4":
  version "8.4.4"
  resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-8.4.4.tgz#0914c6c0540b5a344c7c8fd6072faa1a49af1158"
  integrity sha512-QHi7QcgH/5Jinz+SCfIZJkFHc6Cch1YsAEGFEhi6wSp6MILb0sJMQ1CX06e9tCOAjSlBwaJj4PH0eFCVau5v9Q==
  dependencies:
    axios "0.26.1"
    iterare "1.2.1"
    tslib "2.3.1"
    uuid "8.3.2"

"@nestjs/core@8.4.4":
  version "8.4.4"
  resolved "https://registry.yarnpkg.com/@nestjs/core/-/core-8.4.4.tgz#94fd2d63fd77791f616fbecafb79faa2235eeeff"
  integrity sha512-Ef3yJPuzAttpNfehnGqIV5kHIL9SHptB5F4ERxoU7pT61H3xiYpZw6hSjx68cJO7cc6rm7/N+b4zeuJvFHtvBg==
  dependencies:
    "@nuxtjs/opencollective" "0.3.2"
    fast-safe-stringify "2.1.1"
    iterare "1.2.1"
    object-hash "3.0.0"
    path-to-regexp "3.2.0"
    tslib "2.3.1"
    uuid "8.3.2"

また、OpenAPIのドキュメントを格納するdocディレクトリを作成します。

参照:https://openapi-generator.tech/docs/installation

バックエンド

リポジトリの作成

Github上でバックエンド用のリポジトリを作成し、
sshでローカルにリポジトリをクローンしてきます。

cd Workspace/sun_sun_gold
git clone git@github.com:iizukamaiko/sunsungold_backend.git

空のsunsungold_backendディレクトリが作成されます。

Dockerコンテナ作成

以下に従って、Dockerコンテナ構築の準備をします。
https://github.com/docker/awesome-compose/tree/master/official-documentation-samples/rails/

Dockerfileファイルの作成

Dockerfileを作成します。

touch Dockerfile

root直下にDockerfileファイルが作成されます。

.
└── Dockerfile

このDockerfileファイルを開き、以下のように記載します。
(rubyのバージョンは3.2で指定しています。)

Dockerfile

# syntax=docker/dockerfile:1
FROM ruby:3.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 bundle install

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Configure the main process to run when running the image
CMD ["rails", "server", "-b", "0.0.0.0"]

Gemfileファイルの作成

Gemfileを作成します。

touch Gemfile

root直下にGemfileファイルが作成されます。

.
├── Dockerfile
└── Gemfile

Gemfileファイルを開き、以下のように記載します。
(railsのバージョンは7.0.4以上で指定しています。)

Gemfile

source 'https://rubygems.org'
gem 'rails', '~>7.0.4'

次に、空のGemfile.lockも作成します。

touch Gemfile.lock

以下のような構成になります。

.
├── Dockerfile
├── Gemfile
└── Gemfile.lock

entrypoint.shの作成

entrypoint.shを作成します。

touch entrypoint.sh

以下のような構成になります。

.
├── Dockerfile
├── entrypoint.sh
├── Gemfile
└── Gemfile.lock

このentrypoint.shを作成することで、
server.pidが既に存在していてアプリケーションサーバーが立ち上げられなくなる」というRails特有の問題を解決します。

entrypoint.shファイルを開き、
以下のように記述します。

entrypoint.sh

#!/bin/bash
set -e

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

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

docker-compose.ymlファイルの作成

docker-compose.ymlを作成します。

touch docker-compose.yml

以下のような構成になります。

.
├── docker-compose.yml
├── Dockerfile
├── entrypoint.sh
├── Gemfile
└── Gemfile.lock

docker-compose.ymlを開き、
以下のように記述します。

docker-compose.yml

services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - db

Ruby on RailsのAPIを作成

Ruby on RailsのAPIアプリケーションを作成します。
DBにはpostgresqlを指定しています。

docker compose run --no-deps web rails new . --api --force --database=postgresql

root配下にたくさんのフォルダやファイルが作成されます。
また、Gemfile, Gemfile.lockも更新されます。

dockerイメージの作成

以下コマンドで、最新のDockerイメージを作成します。

docker compose build

DBとの接続設定

config/database.ymlの中身を以下のように書き換えます。

config/database.yml

default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: password
  pool: 5

development:
  <<: *default
  database: sunsungold_development

test:
  <<: *default
  database: sunsungold_test

Dockerコンテナの立ち上げ

以下コマンドで、Dockerコンテナを立ち上げます。

docker compose up

DBの作成

上記でDockerコンテナを立ち上げたターミナルウィンドウとは別に、
新しいターミナルウィンドウを立ち上げ、以下コマンドを実行します。

docker compose run web rake db:create

画面確認

http://localhost:3000/

上記にアクセスし、以下の画面が表示されれば
無事アプリケーションが立ち上がっています、お疲れ様でした!

Dockerコンテナの停止

画面が確認できたので、Dockerコンテナを停止します。
DB作成した方のターミナルウィンドウで、以下を実行します。

docker compose down

Dockerを動かしていた方のターミナルウィンドウを確認すると、
Dockerが停止し、次のコマンドを受け付けている表示になっていると思います。

これで停止できました。

rspecの導入

以下を参考にrspecを導入していきます。
https://github.com/rspec/rspec-rails#installation

Gemfileにrspec-railsを追加します。

Gemfile

group :development, :test do
  # See   https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
  gem "debug", platforms: %i[ mri mingw x64_mingw ]
  gem 'rspec-rails', '~> 6.0.0'  ## この行を追加
end

以下を実行して、ライブラリを追加します。

bundle install

まとめ

一旦、個人開発の際に行ったものを、後から見返せるように記録に残せたかなと思います。
今後は、ここで作成したベースをもとにアプリケーションを作成してきます。

Discussion