rails7.1 ＋ MySQLの環境構築をdockerで行う

# 本ページは
rails + MySQLをコンテナ上で動かせるようにする。railsはweb単体では動かせないので、今回構築するのが最小限の環境になる。
* rails: 7.1.1
* ruby: 3.1.4
* MySQL: 5.7

案件で開発環境を0から作る機会なんてそうそうないと思うので、1回自分のPCでやってみましょう。色々と学びが深いはず。

# ローカル環境
* mac(proの中では最弱)
![スクリーンショット 2023-10-15 1.53.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/948431/0eed060c-fb83-24f7-37ca-4c84581ea498.png)
* docker-compose: v2.22.0-desktop.2
* docker-engine: 24.0.6

dockerさえ入っていれば、linuxでもwindowsでも手順は基本同じ。windowsの場合は適宜コマンドを読み替えて下さい。
# 流れ
1. ディレクトリ、各種設定ファイルを準備
2. rails立ち上げ
3. イメージ構築
4. db作成
5. コンテナ作成&起動

# 内容
## 1. ディレクトリ、各種設定ファイルを準備
* ディレクトリ準備
```
mkdir rails_api_app
cd rails_api_app
```
* 各種ファイルを準備
``` docker:Dockerfile
# FROM：使用するイメージ、バージョン
FROM ruby:3.1.4

# ruby3.1のイメージがBundler version 2.3.7で失敗するので、gemのバージョンを追記
ARG RUBYGEMS_VERSION=3.3.20

# RUN：任意のコマンド実行
RUN mkdir /app

# WORKDIR：作業ディレクトリを指定
WORKDIR /app

# COPY：コピー元とコピー先を指定
# ローカルのGemfileをコンテナ内の/app/Gemfileに
COPY Gemfile /app/Gemfile

COPY Gemfile.lock /app/Gemfile.lock

# RubyGemsをアップデート
RUN gem update --system ${RUBYGEMS_VERSION} && \
    bundle install

COPY . /app

# CMD:コンテナ実行時、デフォルトで実行したいコマンド
# Rails サーバ起動
CMD ["rails", "server", "-b", "0.0.0.0"]
```
rails7.1から立ち上げ時に本番デプロイ用のdockerfileが自動生成されるようになったらしい。つまり、↑このdockerfileは上書きされてしまう模様。
[リリースノート](https://rubyonrails.org/2023/10/5/Rails-7-1-0-has-been-released)

```yaml: docker-compose.yml
version: '3'
services:
  web:
    # 同じフォルダ上のDockerfileを参照させる。特別な事情があればpathを指定してあげる。
    build: .
    command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3001 -b '0.0.0.0'"
    volumes:
      - .:/app
    ports:
      - 3001:3001
    depends_on:
      - db
    # railsでpryする用
    # true を指定することでコンテナを起動させ続けることができます。   
    tty: true
    # stdin_openとは標準入出力とエラー出力をコンテナに結びつける設定です。
    stdin_open: true
  db:
    image: mysql:5.7
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    volumes:
      - db-volume:/var/lib/mysql
    # 環境変数
    environment:
      MYSQL_ROOT_PASSWORD: password
      TZ: "Asia/Tokyo"
    ports:
      - "3306:3306"
# PC上にdb-volumeという名前でボリューム（データ領域）が作成される
# コンテナを作り直したとしてもPC上に残るようにするために設定
volumes:
  db-volume:
```
```gemfile: Gemfile
source 'https://rubygems.org'
gem 'rails', '7.1.1'
```
空の`Gemfile.lock`も一応作っておく。

`entrypoint.sh`でserver.pidを自動で削除させる運用もあるあるらしいがコマンド1つ打てば良いだけだし、`entrypoint.sh`周りでこけることがあったので今回は採用しないことにする。

## 2. rails立ち上げ
* apiモードで立ち上げ
```
% docker-compose run --rm web rails new . --force --database=mysql --api
```

* `dockerfile`修正
先述の通り、railsを立ち上げるとdockerfileが上書きされる。それにより一部不整合が怒るので編集する必要あり。

```docker:Dockerfile
RAILS_ENV="development"
```
立ち上げ後は`production`になっているはず。

## 3. イメージ構築
```
% docker-compose build
```
とりあえずbuild
## 4. db作成
* `config/database.yml`修正
```yaml:config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  host: db
```
`docker-compose.yml`に定義したpassword, hostに修正する。passwordは`MYSQL_ROOT_PASSWORD`、hostはservices配下で定義している名前。（今回はweb,dbとしている。）

config書き換えたので一応
```
% docker-compose build
```
* db作成
別ターミナルでdbを立ち上げておく。
```
docker-compose up db
```
そしてdb:create
```
docker-compose run --rm web bundle ex rails db:create
```
bundle越しにrailsを叩いてやる必要がある。/binを叩いたり、他にも方法はあるが今回は一番お手軽な方法で。

db:createできたら、立ち上げたdbを落としてok。

## 5. コンテナ作成&起動
```
% docker-compose up -d
```
http://localhost:3001/ にアクセスできれば完了。

# これからやりたいこと
* lint, rubcopの導入
* makefileの整備
* web, dbの拡張（案件で触っている環境の簡易版を作ってみるのも良いかも）

今回構築した環境は一応[git](https://github.com/takeba-takeba/rails-sample)にも上げてます。

# 参考
* [Rails 7 + MySQLの環境構築をDocker composeで作る](https://qiita.com/croquette0212/items/7b99d9339fd773ddf20b)
* [Dockerを用いてRuby on Railsの環境構築をする方法( Docker初学者向け )](https://qiita.com/Yusuke_Hoirta/items/3a50d066af3bafbb8641)
* [exec /usr/local/bin/docker-entrypoint.sh: exec format error](https://qiita.com/OmeletteCurry19/items/fd057a7448aa3072fd1e)
（自分は結局↑のエラーが解消せずentrypointを外したが...）