Closed14

Rails API/Next.js/PostgreSQL/Docker/Fly.io/Vercel

Ippei ShimizuIppei Shimizu

参考記事

https://blog.furu07yu.com/entry/rails-nextjs-monorepo-docker-setup
https://zenn.dev/taku1115/articles/6c9fa97ab37e38

フロントエンド・バックエンドディレクトリのサブモジュール化

├── rails-api-nextjs-verification-app
  ├── front
  └── back
  • メインリポジトリを作成。
  • front/backディレクトリのリポジトリ作成。
  • サブモジュール追加
rails-api-nextjs-verification-app $ git submodule add [フロントエンドリポジトリのURL] front
rails-api-nextjs-verification-app $ git submodule add [バックエンドリポジトリのURL] back
  • メインリポジトリ変更のコミットとプッシュ
rails-api-nextjs-verification-app $ git add .
rails-api-nextjs-verification-app $ git commit -m "Add: submolues"
[submodule "front"]
	path = front
	url = [フロントエンドリポジトリのURL]
[submodule "back"]
	path = back
	url = [バックエンドリポジトリのURL] 

Image from Gyazo

Ippei ShimizuIppei Shimizu

バックエンド側作成

Docker環境構築

├── rails-api-nextjs-verification-app
    ├── front/
    └── back/
    ├── docker-compose.yml 
  • ルートディレクトリにdocker-compose.ymlを配置する。
Ippei ShimizuIppei Shimizu
docker-compose.yml
version: "3"
services:
  db:
    image: postgres:latest
    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
  front:
    build:
      context: ./front/
      dockerfile: Dockerfile
    volumes:
      - ./front:/app
    command: yarn dev -p 4000
    ports:
      - "8000:4000"
volumes:
  postgres_data:
Ippei ShimizuIppei Shimizu

Dokerfile作成

├── rails-api-nextjs-verification-app
    ├── front/
        ├── Dockerfile
    └── back/
        ├── Dockerfile
    ├── docker-compose.yml 
/back/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"]
#!/bin/bash
set -e

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

exec "$@"
/front/Dockerfile
FROM node:19.4.0
WORKDIR /app
Ippei ShimizuIppei Shimizu
  • Gemfile作成
Gemfile
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby "3.2.2"

gem "rails", "~> 7.0.5"
  • Gemfile.lock作成(空)
├── rails-api-nextjs-verification-app
    ├── front/
        ├── Dockerfile
    └── back/
        ├── Dockerfile
        ├── Gemfile
        ├── Gemfile.lock
    ├── docker-compose.yml 
$ docker-compose build
Ippei ShimizuIppei Shimizu

Next.jsアプリ作成

エラー

% docker-compose run --rm front yarn create next-app .
yarn create v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Installed "create-next-app@14.0.3" with binaries:
      - create-next-app
[##] 2/2The directory app contains files that could conflict:

  Dockerfile

Either try using a new directory name, or remove the files listed above.

error Command failed.
Exit code: 1
Command: /usr/local/bin/create-next-app
Arguments: .
Directory: /app
Output:

info Visit https://yarnpkg.com/en/docs/cli/create for documentation about this command.

原因は、frontディレクトリ内のDockerfileとappディレクトリが競合していたため。Dockerfileを一時的に、ルートディレクトリへ移動した。

$ docker-compose run --rm front yarn create next-app .
$ docker-compose up front

以下の画面が表示されれば完了。
Image from Gyazo

Ippei ShimizuIppei Shimizu

Rails APIモード環境構築

docker-compose run --rm --no-deps back bundle exec rails new . --api --database=postgresql

config/application.rbに以下を追加

    config.time_zone = 'Tokyo'
    config.active_record.default_timezone = :local
    config.i18n.default_locale = :ja

config/environments/development.rbに以下を記述することで、指定されたホスト名からのリクエストを許可することができます。

Rails.application.configure do
・・・
  config.hosts << "api"
end

データベースのセットアップ

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: user
  password: password
  host: db
docker-compose run --rm back rails db:create
% docker-compose run --rm back rails db:create
[+] Running 14/14
 ✔ db 13 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿]      0B/0B      Pulled                                                                                                                                                    36.5s
   ✔ 31ce7ceb6d44 Pull complete                                                                                                                                                                           16.8s
   ✔ 28caef79f6ed Pull complete                                                                                                                                                                           16.8s
   ✔ be24e278ddaa Pull complete                                                                                                                                                                           16.9s
   ✔ dfdbb4d6f9a3 Pull complete                                                                                                                                                                           17.0s
   ✔ ebb06cfd45ec Pull complete                                                                                                                                                                           17.2s
   ✔ 9738a56db3f9 Pull complete                                                                                                                                                                           17.3s
   ✔ 87cb08d2765c Pull complete                                                                                                                                                                           17.3s
   ✔ d99960ffd545 Pull complete                                                                                                                                                                           17.4s
   ✔ 4323262571df Pull complete                                                                                                                                                                           30.6s
   ✔ b0626670078e Pull complete                                                                                                                                                                           30.6s
   ✔ 1ee7ca4fb425 Pull complete                                                                                                                                                                           30.7s
   ✔ eb3cb400d64e Pull complete                                                                                                                                                                           30.7s
   ✔ f6218791bc49 Pull complete                                                                                                                                                                           30.8s
[+] Running 1/1
 ✔ Container rails-api-nextjs-verification-app-db-1  Created                                                                                                                                               0.5s
[+] Running 1/1
 ✔ Container rails-api-nextjs-verification-app-db-1  Started                                                                                                                                               0.3s
Could not find pg-1.5.4, puma-5.6.7, bootsnap-1.17.0, debug-1.8.0, msgpack-1.7.2, irb-1.9.1, reline-0.4.0, rdoc-6.6.0, psych-5.1.1.1, stringio-3.0.9 in locally installed gems
Run `bundle install --gemfile /app/Gemfile` to install missing gems.
$ docker-compose run --rm back bundle install
$ docker-compose build back
docker-compose run --rm back rails db:create
docker-compose up

Image from Gyazo

Ippei ShimizuIppei Shimizu

API作成

scaffold追加

docker-compose run --rm back bundle exec rails g scaffold post title:string
docker-compose run --rm back bundle exec rails db:migrate
seeds.rb
# seeds.rb
Post.create!(
  [
    { title: '野球のルール基礎知識' },
    { title: 'プロ野球選手のトレーニング方法' },
    { title: '野球の歴史とは' },
    { title: 'メジャーリーグと日本プロ野球の違い' },
    { title: '野球用具の選び方' },
    { title: '野球のポジション紹介' },
    { title: '野球の戦術入門' },
    { title: '子供向け野球教室の選び方' },
    { title: '高校野球の魅力' },
    { title: '野球観戦の楽しみ方' },
    { title: '野球のスコアブックのつけ方' },
    { title: '野球の審判の役割' },
    { title: '野球におけるピッチングの技術' },
    { title: 'バッティングの基本' },
    { title: '野球の名言集' },
    { title: '野球のトレーニング用品紹介' },
    { title: '野球選手の食事管理' },
    { title: '野球の怪我の予防と対処法' },
    { title: '野球の上達法' },
    { title: '野球の国際大会について' }
  ]
)
docker-compose run --rm back bundle exec rails db:seed
Ippei ShimizuIppei Shimizu

rack-cors追加

Gemfile
gem "rack-cors"
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'localhost:8000', '127.0.0.1:8000'

    resource "*",
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end
docker-compose run --rm back bundle install

再ビルド

docker-compose build back
Ippei ShimizuIppei Shimizu

Next.jsをVercelへデプロイする

frontリポジトリをVercelと連携させる。
https://zenn.dev/dollaga_saiore/articles/2b9158e5add3c6

RailsをFly.ioにデプロイする

  • backディレクトリで、fly launchを実行。
  • 以下のエラー発生。
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
An error occurred while installing pg (1.5.4), and Bundler cannot
continue.

In Gemfile:
  pg
Error: Failed to install bundle, exiting: exit status 5

brew install postgresqlで解決。
fly deploy
fly apps open

Ippei ShimizuIppei Shimizu

GithubActions

Vercel

  • VercelのToken取得
  • VercelCLI

Fly.io
372761 GB/s × VM: Additional RAM (at $0.00000193 / month)と1287 GB/hr × Volume: SSD Storage (at $0.0002083333 / month)の料金が発生してしまった。

無料枠

  • 最大 3 つの共有 CPU-1x 256mb VM
  • 3 GB 永続ボリューム ストレージ (合計)
  • 160GBの送信データ転送

372761 GB/s × VM: Additional RAM (at $0.00000193 / month)

仮想マシン(VM)で使用された追加RAM(ランダムアクセスメモリ)に対する請求です。

  • まず、仮想マシン(VM)ってなんだ

    • 物理的なハードウェア上で仮想的に作成されるコンピューターシステムです。一つの物理サーバー上で複数のVMを実行することができます。
    • ビル全体がハードウェアを表すと、各オフィスが1つのVMに相当する。
  • RAM(ランダムアクセスメモリ)ってなんだ

    • データを一時的に保存し、高速にアクセスするためのメモリです。
    • オフィスの机に相当します。机が大きければ作業領域が広くなり、効率が向上するイメージです。

Fly.ioでは、無料枠で使用できるVM(最大3つの共有CPU VM)とRAM(256MBまで)のサイズが決まっており、なぜかその枠を超えてしまっていたみたいです。

今回のRailsAPIアプリケーションでは、どこでRAMを使用していたのか。

  • データベース操作、リクエストの処理、アプリケーションロジックの実行などがRAMを消費するみたいです。
  • PostgreSQLデータベースもまた、データの保存、クエリの実行、キャッシュ管理などにRAMを使用するみたいです。
  • Dockerコンテナのリソースも関係あるみたい。

余分なRAMの使用量が原因っぽい。余分なRAMの使用量を削減する。

もう一度、デプロイしてみる。
$ fly launch
Memory & CPUVM Sizes= shared-cpu-1x、VM Memory=256MB
DatabaseConfiguration=Development - Single node, 1x shared CPU, 256MB RAM 1GB disk

Ippei ShimizuIppei Shimizu

Fly.ioへのデプロイが失敗する

Fly.ioで設定されているアプリケーションの機械(マシン)の最大数に達したため発生している。

-------
 ✖ [1/2] Machine 148e441fd52989 [app] update failed: failed to update VM 148e441fd52989: You have reached the maximum number of machines for this app…
   [2/2] Waiting for job
-------
Error: failed to update VM 148e441fd52989: You have reached the maximum number of machines for this app.
このスクラップは5ヶ月前にクローズされました