Next.js x Typescript x Docker x Rails APIの環境構築まで
技術スタック
- 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 test
をyarn 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コンテナ構築の準備をします。
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
画面確認
上記にアクセスし、以下の画面が表示されれば
無事アプリケーションが立ち上がっています、お疲れ様でした!
Dockerコンテナの停止
画面が確認できたので、Dockerコンテナを停止します。
DB作成した方のターミナルウィンドウで、以下を実行します。
docker compose down
Dockerを動かしていた方のターミナルウィンドウを確認すると、
Dockerが停止し、次のコマンドを受け付けている表示になっていると思います。
これで停止できました。
rspecの導入
以下を参考にrspecを導入していきます。
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