Rails7の環境構築 (Docker, Bootstrap)


普段はC言語を触っていますが、
ちょっと別の案件でRailsやらDockerやらを触る必要があったので備忘録的に書いてみます。

### 参考にした記事
* [Docker + Rails7 + bootstrap5](https://qiita.com/mkt1234/items/b852eeeb213e46702236)
* [Ruby on Rails 7 with Bootstrap on Docker Compose 開発環境を簡単に構築する方法](https://qiita.com/normalsalt/items/8bf6c5010c9e9f127582)

## 開発環境構築
### ディレクトリを作成
```
mkdir rails
cd rails
```

### 各種設定ファイルを作成
以下のファイルを作成する。
##### Dockerfile
いろいろ試してみたが、上手くいかなかったので[こちら](https://qiita.com/mkt1234/items/b852eeeb213e46702236)のDockerfileを参考にさせていただいた。
```　 Dockerfile
FROM ruby:3.2.0
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -\
    && echo 'deb http://dl.yarnpkg.com/debian/ stable main' > /etc/apt/sources.list.d/yarn.list
RUN curl -sL https://deb.nodesource.com/setup_16.x | bash -
RUN apt update -qq && apt install -y nodejs build-essential yarn \
    curl dirmngr apt-transport-https lsb-release ca-certificates

ENV APP_ROOT /myapp
RUN mkdir ${APP_ROOT}
WORKDIR ${APP_ROOT}
COPY Gemfile ${APP_ROOT}/Gemfile
COPY Gemfile.lock ${APP_ROOT}/Gemfile.lock
RUN bundle install
COPY . ${APP_ROOT}

# 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"]

```
##### docker-compose.yml
``` docker-compose.yml
version: "3.9"
services:
  db:
    image: mysql
    volumes:
      - ./tmp/db:/var/lib/mysql
    environment:
      MYSQL_ROOT_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:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
    tty: true
    stdin_open: true
```
参考→[docker-compose.ymlの書き方について解説してみた](https://qiita.com/yuta-ushijima/items/d3d98177e1b28f736f04)

##### Gemfile
``` Gemfile
source 'https://rubygems.org'
gem "rails", "~> 7.0.4", ">= 7.0.4.2"
```
##### Gemfile.lock
このファイルの中身は空のまま

##### entrypoint.sh
``` entrypoint.sh
#!/bin/bash
set -e

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

exec "$@"

```

### rails new
```
% docker-compose run --rm --no-deps web rails new . --force --database=mysql --css=bootstrap
```
`--css=bootstrap`オプションで、Bootstrapを使用するように設定

#### package.jsonの確認
`rails new`が終わった時点で、以下のように`package.json`の内容が欠落していることがある。
``` package.json
{
  "name": "app",
  "private": "true"
}
```
[こちら](https://qiita.com/mkt1234/items/b852eeeb213e46702236#packagejson-%E7%B7%A8%E9%9B%86)の記事でも同じようなことが起きていたみたい

上手くいっていればこんな感じ
``` package.json
{
  "name": "app",
  "private": "true",
  "dependencies": {
    "@hotwired/stimulus": "^3.2.1",
    "@hotwired/turbo-rails": "^7.2.5",
    "@popperjs/core": "^2.11.6",
    "bootstrap": "^5.2.3",
    "bootstrap-icons": "^1.10.3",
    "esbuild": "^0.17.5",
    "sass": "^1.58.0"
  },
  "scripts": {
    "build": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds --public-path=assets",
    "build:css": "sass ./app/assets/stylesheets/application.bootstrap.scss:./app/assets/builds/application.css --no-source-map --load-path=node_modules"
  }
}
```
私は最初からやり直してましたが、ちゃんとした対応とか対策ってどうやるのが正解なのか？

### database.ymlを編集
``` database.yml
# MySQL. Versions 5.5.8 and up are supported.
#
# Install the MySQL driver
#   gem install mysql2
#
# Ensure the MySQL gem is defined in your Gemfile
#   gem "mysql2"
#
# And be sure to use new-style password hashing:
#   https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html
#
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  # 以下の２行を変更
  password: password
  host: db
```
`password:` にはdocker-compose.yml の `MYSQL_ROOT_PASSWORD:`のパスワードと同じものを、
`host:` には docker-compose.ymlで命名したMySQLのコンテナ名`db`を記載

<!--
### Gemfileを修正
DockerfileでRuby`3.2.0`を指定しているので、Gemfileのrubyを修正
```
ruby "3.2.0"
```
-->

### バックグラウンドでコンテナ起動
```
% docker-compose up -d --build
```
`docker-compose ps`で起動しているか確認
```
% docker-compose ps
NAME                IMAGE               COMMAND                  SERVICE             CREATED             STATUS              PORTS
rails-db-1            mysql               "docker-entrypoint.s…"   db                  10 minutes ago      Up 10 minutes       3306/tcp, 33060/tcp
rails-web-1           web-web             "entrypoint.sh bundl…"   web                 53 seconds ago      Up 52 seconds       0.0.0.0:3000->3000/tcp
```
`STATUS`が`UP`になっていればOK

### データベースを作成
```
% docker-compose exec web rails db:create
```

## localhost:3000にアクセス
`localhost:3000`にアクセスし、railsのページが表示されていればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213802/6870c2f9-6680-1269-8d51-07e41fedc6c6.png)


### bootstrapの確認
適当にビューとコントローラを作りbootstrapを確認
```
docker-compose exec web rails generate controller Home index
```

``` index.html.erb
<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <div class="container-fluid">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
        <li class="nav-item">
          <a class="nav-link active" aria-current="page" href="#">Home</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#">Link</a>
        </li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
            Dropdown
          </a>
          <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
            <li><a class="dropdown-item" href="#">Action</a></li>
            <li><a class="dropdown-item" href="#">Another action</a></li>
            <li><hr class="dropdown-divider"></li>
            <li><a class="dropdown-item" href="#">Something else here</a></li>
          </ul>
        </li>
        <li class="nav-item">
          <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
        </li>
      </ul>
      <form class="d-flex">
        <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
        <button class="btn btn-outline-success" type="submit">Search</button>
      </form>
    </div>
  </div>
</nav>
```

これだけだと、ドロップダウンが動かない
```
docker-compose exec web rails assets:precompile
```
これでドロップダウンが動くようになる