【2024年1月版】DockerでRails7の環境構築(esbuild,bootstrap,MySQL8)

# 0. はじめに
DockerでRails7の環境を構築する手順（2024/02時点)です。
Javascript：esbuild
DB：MySQL8
CSS：Bootstrap
で作ります。
うまく動かないところがあったので改めて書き直しています。

# 1.　環境

環境: MacOS Sonoma(14.2.1)
CPU: M1
Docker Desktopはインストール済
```sh:
$ docker -v
Docker version 25.0.2, build 29cf629d
$ docker compose version
Docker Compose version v2.23.3
```
# 2. ディレクトリ
ディレクトリ構成
rails7appディレクトリを作成し、配下にdockerディレクトリを作成。
```
mkdir rails7app
cd rails7app
```
# 3. 各種設定ファイルを作成
- railsappフォルダにrailsを構築。Dockefileを分けておかないと、Rails7構築時に上書きされてしまう。
- docker3.0以降docker-compose.ymlではなく、compose.yamlを使う。
- compose.yaml,DockerfileとGemfile、Gemfile.lockはカレントに置いて、Dockefileでrailsのルートにコピー。
- entrypoint.shは後ほど使うので空のファイル。
```sh:
touch {compose.yaml,Dockerfile,Gemfile,Gemfile.lock,entrypoint.sh} && mkdir railsapp
```
この時点でのtree
```sh:
rails7app
├── Dockerfile
├── Gemfile
├── Gemfile.lock
├── compose.yaml
├── entrypoint.sh
└── railsapp/
```

# 4. Dockerfileの記述
+ のちのちrails dbconsoleをする場合、mysql-clientが必要だが、mariadb-clientに統合された
+ curl -fsSLの部分はnodeのlts（v18.0)をインストールするために必要。ruby3.2.0のイメージでは、nodeのバージョンが12で古すぎるため。
+ ENVで環境変数としてAPPのルートを渡す
```sh:Dockerfile
FROM ruby:3.2.0
ENV APP /railsapp
ENV LANG C.UTF-8
ENV TZ Asia/Tokyo
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
RUN apt update -qq \
 && apt install -y build-essential mariadb-client nodejs \
 && npm install --global yarn
RUN yarn add @fortawesome/fontawesome-free @fortawesome/fontawesome-svg-core @fortawesome/free-brands-svg-icons @fortawesome/free-regular-svg-icons @fortawesome/free-solid-svg-icons
WORKDIR $APP
COPY Gemfile $APP/Gemfile
COPY Gemfile.lock $APP/Gemfile.lock
RUN bundle install
```

# ５. Gemfileの記述
バージョンは固定しておいた方が無難
最新のrailsバージョンを調べる
```sh:
gem search -ra "^rails$"
*** REMOTE GEMS ***

rails (7.1.3, 7.1.2, 7.1.1, 7.1.0, 7.0.8, 7.0.7.2, 7.0.7.1, 7.0.7, 7.0.6, 7.0.5.1, 7.0.5, 7.0.4.3, 7.0.4.2, 7.0.4.1, 7.0.4, 7.0.3.1, 7.0.3, 7.0.2.4, 7.0.2.3, 7.0.2.2, 7.0.2.1, 7.0.2, 7.0.1, 7.0.0, 6.1.7.6,.........
```
7.1.3のようだ（2024/02/13時点)
```:Gemfile
source 'https://rubygems.org'
gem 'rails', '~>7.1.3'
```
# ６. compose.yaml
Docker Desktop v3.0.0から色々変わった。

https://kojinjigyou.org/48322/
+ docker-composeはdockerコマンドのサブコマンドになった。
  docker-compose ~ではなくdocker compose ~と実行する
+ 設定ファイルであるdocker-compose.ymlはcompose.yamlに変わった。
+ version指定が必要なくなった。
+ /usr/local/bundleをgemdataとしてvolumeマウントさせないと、gem周りでエラーが出まくる。
```yaml:compose.yaml
services:
  db:
    restart: always
    image: mysql:8.0
    # DBのレコードが日本語だと文字化けするので、utf8mb4をセットする
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    volumes:
      - type: volume
        source: mysqldata
        target: /var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
      TZ: "Asia/Tokyo"
    ports:
      - '3306:3306'
  webapp:
    #buildの"."はカレント(.)にあるDockerfileを参照してbuildしろということ
    build: .
    #rails7ではrails sではなく.bin/devでwebサーバーを起動させる(development)
    command: bash -c "rm -f tmp/pids/server.pid && ./bin/dev"
    volumes:
      - type: bind
        source: ./railsapp
        target: /railsapp
      - type: volume
        source: gemdata
        target: /usr/local/bundle
      - type: volume
        source: node_modules
        target: /railsapp/node_modules
    ports:
      - "3000:3000"
    depends_on:
      - db
    stdin_open: true
    tty: true
    environment:
      MYSQL_PASSWORD: password
      TZ: "Asia/Tokyo"
volumes:
  gemdata:
  node_modules:
  mysqldata:
```
# 7. railsプロジェクトを作る
- 以前はデフォルトでjavascriptアプローチがesbuildになっていたが、7.1.3ではesbuildを明示してやる必要がある。
```sh:
docker compose run --rm --no-deps webapp rails new . --force --css bootstrap --javascript esbuild --database mysql
```
このコマンドを打つとずらずらとrailsファイルが作成される。
+ オプション
--force : ファイルが存在する場合に上書き
--css : cssプロセッサでbootstrapを指定
--javascript : javascriptアプローチでesbuildを指定
–-database : データベースの種類(デフォルトがsqlite3なので、それ以外の時は指定する。)
※重要！！！
–-skip-bundleでスキップしてはいけません。

# 8. config/database.yml
railsapp/config以下のdatabase.ymlを編集する。
```yaml:config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  #　この部分はmysqlコンテナを指定
  host: db
  # portを指定しないとMySQL connectエラーになりdbを作成できない
  port: 3306
```
# 9. Procfile.dev
「-b 0.0.0.0 -p 3000」を付加する。これが無いとlocalhostでアクセスできない。
-pはコンテナ側でLISTENしているポート

```:Procfile.dev
# web: unset PORT && env RUBY_DEBUG_OPEN=true bin/rails server
web: unset PORT && env RUBY_DEBUG_OPEN=true bin/rails server -b 0.0.0.0 -p 3000
js: yarn build --watch
css: yarn watch:css
```

# 10. MySQLのDBを作成
```sh:
docker compose run --rm webapp rails db:create
```

# 11. コンテナの作成と起動
-dをつけることでバックグラウンドで起動
```sh:
docker compose up -d
```

# 12. サーバの起動を確認
http://localhost:3000

にアクセスし、rails7の初期画面になっていればOK
![スクリーンショット 2023-07-25 15.43.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82975/d8718e85-6719-6e23-3540-d85d58a524e5.png)

# 13. bootstrapの確認
確認用のcontrollerを作成し、viewを作成
コンテナをupさせたまま行うのでrunではなくexecで
```sh
docker compose exec webapp rails g controller hello index
```
bootstrapが適用されているか確認するために
app/views/hello/index.html.erbを以下のように書き換えます。
```rb:app/views/hello/index.html.erb
<div class="container">
  <h1>Hello#index</h1>
  <p>Find me in app/views/hello/index.html.erb</p>
  <div class="btn-group">
    <button type="button" class="btn btn-danger dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
      Action
    </button>
    <ul class="dropdown-menu">
      <li><a class="dropdown-item" href="#">Action</a></li>
      <li><a class="dropdown-item" href="#">Another action</a></li>
    </ul>
  </div>
  <div>
    <h5>
      Fontawesome Icon
    </h5>
    <div style="font-size: 5rem; color: cornflowerblue;">
      <i class="fas fa-space-shuttle"></i>
      <i class="fas fa-snowman"></i>
      <i class="fas fa-kiwi-bird"></i>
    </div>
  <div>
  <div>
    <h5>
      Bootstrap Icons
    </h5>
    <div style="font-size: 5rem; color: orange;">
      <i class="bi bi-boxes"></i>
      <i class="bi bi-radioactive"></i>
      <i class="bi bi-alarm"></i>
    </div>
  </div>
</div>
```
http://localhost:3000/hello/index
下のようになっていればOK。bootstrapの体裁になっている。
Actionのドロップダウンも有効になっている（esbuildが効いているということ）。
この時点ではbootstrapだけ。fontawesomeのアイコンはインストールされていないので表示されていない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82975/4ccd513f-b9a6-5a09-6331-f5c50bc9c66f.png)

# 14. Fontawesomeの設定
※ここからは筆者の好みなので必須ではありません。
　Fontawesomeのインストールは済。（Dockerfileに記載）
##### app/javascript/application.jsに以下を追加
```sh:
import '@fortawesome/fontawesome-free'
import { fas } from '@fortawesome/free-solid-svg-icons'
import { far } from '@fortawesome/free-regular-svg-icons'
import { fab } from '@fortawesome/free-brands-svg-icons'
import { library } from "@fortawesome/fontawesome-svg-core";
library.add(fas, far, fab)
```
先ほどは表示されていなかったFontawesomeのアイコンが表示されるようになった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82975/23196939-54ff-3a53-f7a2-8030f5589cdb.png)

# 参考

https://qiita.com/jibiking/items/fc7b0141af4b13a32ec3

https://zenn.dev/wakkunn/articles/33c84147608078

https://qiita.com/akky-tys/items/60d8ffce50b5600c5af4