docker+vite+vue3環境のバックエンドにrailsを設定

# 想定
以下で構築したフロントエンドvite+vue3の環境にバックエンドとしてapiモードのrailsを追加します。

https://qiita.com/devzooiiooz/private/45079e52d4a7d4d25d40

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82975/899f031c-276d-b6c0-38e4-f1d97066453a.png)


# 前準備
+ direnvのインストールと有効化
プロジェクトルート直下でに.envrcを作成する。
direnvはホスト側のみでよい。
```sh:
touch .envrc
```
+ .envrcに環境変数を設定
```env:.envrc
# MySQL
export DATABASE_USERNAME='root'
export DATABASE_PASSWORD='password'
export DATABASE_HOST='db'
```
+ direnvの有効化
```sh:
direnv allow
```
# backendの設定
+ ディレクトリ作成
```sh:
mkdir backend && mkdir backend/api
```
+　必要ファイル(Dockerfile,Gemfile,Gemfile.lock)作成
```sh:
cd backend && touch {Dockerfile,Gemfile,Gemfile.lock}
```
+ Dockerfile
```ruby:Dockerfile
FROM ruby:3.2.0
ENV APP /api
ENV TZ Asia/Tokyo
RUN apt-get update -qq && apt-get install -y mariadb-client nano
WORKDIR $APP
ADD Gemfile $APP/Gemfile
ADD Gemfile.lock $APP/Gemfile.lock
RUN bundle install
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
```

+ Gemfile
```ruby:Gemfile
source 'https://rubygems.org'
gem 'rails', '~>7.1.3'
```

+ Gemfile.lockは空でOK

+ compose.yaml
backendの設定(dbはmysql,apiはrails7)を追加する
```diff_yaml:compose.yaml
services:
  frontend:
    build: ./frontend/
    volumes:
      - type: bind
        source: ./frontend/app
        target: /app
    ports:
      - "8082:5173"
+  db:
+    image: mysql:8.0
+    platform: linux/x86_64
+    restart: always
+    command: mysqld --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
+    environment:
+　　　　　　　　  TZ: Asia/Tokyo
+      MYSQL_ROOT_PASSWORD: $DATABASE_PASSWORD
+    volumes:
+      - type: volume
+        source: mysqldata
+        target: /var/lib/mysql
+  api:
+    build: ./backend/
+    platform: linux/x86_64
+    environment:
+      TZ: Asia/Tokyo
+      DATABASE_USERNAME: $DATABASE_USERNAME
+      DATABASE_PASSWORD: $DATABASE_PASSWORD
+      DATABASE_HOST: $DATABASE_HOST
+    volumes:
+      - type: bind
+        source: ./backend/api
+        target: /api
+      - type: volume
+        source: gemdata
+        target: /usr/local/bundle
+    ports:
+      - "8083:3000"
+    depends_on:
+      - db
+ volumes:
+   mysqldata:
+   gemdata:
```
+ rails7をapiモード+db:mysqlで構築する
```sh:
docker compose run --rm api rails new . --api --database=mysql --skip-yarn --skip-active-storage --skip-javascript --skip-turbolinks --skip-test
```

+ railsのdb設定
```yaml:backend/api/config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  charset: utf8mb4
  collation: utf8mb4_general_ci
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch("DATABASE_USERNAME") %>
  password: <%= ENV.fetch("DATABASE_PASSWORD") %>
  host: <%= ENV.fetch("DATABASE_HOST") %>
  port: <%= ENV.fetch('DATABASE_PORT') { 3306 } %>
~略~
```
+ db作成
```sh:
docker compose run --rm api rails db:create
```
+ コンテナ起動
```sh:
docker compose up -d
```
+ rails起動確認
http://localhost:8083 にアクセスし、railsの起動を確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82975/f7699a14-fa1f-375f-4366-44b7edf3bb72.png)

+ railsにrack-corsをインストール
apiモードなのでGemfileのコメントアウトを外すだけ
```diff_ruby:Gemfile
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin Ajax possible
- # gem "rack-cors"
+ gem "rack-cors"
```
+ bundle install
```sh:
docker compose run --rm api bundle install
```

+ backend/api/config/initializers/cors.rbを修正
```diff_ruby:cors.rb
# Be sure to restart your server when you modify this file.

# Avoid CORS issues when API is called from the frontend app.
# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin Ajax requests.

# Read more: https://github.com/cyu/rack-cors
+ 以下のコメントアウトを外しoriginsを設定（frontend側のポート）
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins "localhost:8082"
    resource "*",
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end
```
+ ackend/api/config/environments/development.rbに「config.hosts.clear」を追加
```diff_ruby:development.rb
  # Raise error when a before_action's only/except options reference missing actions
  config.action_controller.raise_on_missing_callback_actions = true
+ ## 以下を追加
+  config.hosts.clear
```
これでfrontend側のvueからaxiosなりfetchすればバックエンドのrailsのデータが取得できます。