【初学者向け】Docker 上で Rails 環境を構築しよう！

# はじめに
この記事では Docker 上で Rail の環境を構築して、scaffold を用いたサンプルアプリケーションを作成するところまでを説明します。全部でたったの３ステップで終わります。
Docker Desktop はインストール済みであることを前提としています。
また、バージョンに関しては`rails チュートリアル (第６版)`にあわせていますので、必要に応じてバージョンを変更してください。

# 1. 設定ファイルの作成

まずは作業をするディレクトリを作成し、移動します。

```
mkdir rails_test
cd rails_test
```


次に、下記のコマンドで５つの設定ファイルを作成します。
```
touch {Dockerfile,docker-compose.yml,Gemfile,Gemfile.lock,entrypoint.sh} 
```


最後に、各ファイルに下記のコードをコピペしてください。



### Dockerfile

```dockerfile
FROM ruby:2.7.6

# yarn, curl, apt-transport-https, wget, nodejs をインストール。
# 最後に、不要なキャッシュやパッケージリストを削除し、Dockerイメージのサイズを最小限に抑える。
RUN apt-get update && apt-get install -y curl apt-transport-https wget nodejs && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && apt-get install -y yarn && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

# 作業ディレクトリ
RUN mkdir /app
WORKDIR /app

# ローカルのGemfileをコンテナへコピー
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
# Gemfile に記載されているgem(ここでは Rails)をインストール
RUN bundle install

# ソースコードをコンテナへコピー
COPY . /app

# JSの依存パッケージをインストール、アセットをコンパイル
RUN yarn install --check-files
RUN bundle exec rails webpacker:compile

# Rails特有の問題を回避するために、コンテナ実行時にPIDファイルを削除
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]

# 3000番ポートを設定
EXPOSE 3000

# Railsサーバを起動
CMD ["rails", "server", "-b", "0.0.0.0"]
```




### Docker-compose.yml

```yml
version: '3'
services:
  # データベース
  db:
    image: mysql:5.7                     # イメージ
    environment:
      MYSQL_ROOT_PASSWORD: password      # rootユーザのパスワード
    ports:
      - "3306:3306"                      # ホストとコンテナのポートをマッピング
    volumes:
      - db-volume:/var/lib/mysql         # ボリュームマウント (データの永続化)

  # アプリケーションサーバ
  web:
    build: .                             # Dockerfileからイメージをビルド
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"  # PIDファイルの削除、サーバの起動
    volumes:
      - .:/app                           # バインドマウント (コードの変更をリアルタイムで反映)
    ports:
      - "3000:3000"                      # ホストとコンテナのポートをマッピング
    depends_on:
      - db                               # db に依存していることを明示

# ボリュームの作成
volumes:
  db-volume:
```

### entrypoint.sh

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

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

exec "$@"

```



### Gemfile

```
source 'https://rubygems.org'
gem 'rails', '~> 6.0.4'
```



### Gemfile.lock
※ Gemfile.lock は空のままで大丈夫です。

```

```






# 2. コマンドの実行

- 下記のコマンドはDocker Composeで定義した web サービスにて `rails new . --force --database=mysql` コマンドを実行します。これは新しいRailsアプリケーションを現在のディレクトリに作成します。
また、 `--force` オプションは既存のファイルを上書きし、`--database=mysql` はデータベースとしてMySQLを使用することを指定します。
`--rm` は、コマンドの実行が終了したらコンテナを削除することを指定します。
  ```
  docker-compose run --rm web rails new . --force --database=mysql
  ```
- Docker Composeによって定義された **webサービス** と **db サービス** をビルド(Dockerイメージを生成)します。
  ```
  docker-compose build
  ```



- `/config/database.yml` の **password** と **host** を、Dockerfileで設定したものに修正します。

  ```yml
  default: &default
    adapter: mysql2
    encoding: utf8mb4
    pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
    username: root
    password: password    # <- password を入力
    host: db              # <- localhost から db に変更
  ```


- web サービスにて、 rails db:create コマンドを実行します。これにより、データベースが作成されます。

  ```
  docker-compose run --rm web rails db:create
  ```


- Docker Composeによって定義されたすべてのサービスをバックグラウンドで起動します（ `-d` は "detached mode" を指す）。これにより、RailsアプリケーションとMySQLデータベースが起動し、アプリケーションが稼働し始めます。

  ```
  docker-compose up -d
  ```

- `localhost:3000` にアクセスして動作確認
    以下の画像と同じ画面が表示されていれば成功です！
    (コンテナ起動直後はアクセスに時間がかかることがありますのでしばらくお待ちください)

    ![スクリーンショット 2023-06-06 13.00.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2550355/f7ced983-286f-bfd6-394c-8434540a2ae6.png)


- docker-compose downコマンドは、Docker Composeで作成、起動したすべてのサービスを停止し、それらのサービスのコンテナ、ネットワーク、ボリューム、イメージを削除します。
- 
  ```
  docker-compose down
  ```

# 3. 簡単なアプリ を動かしてみよう！

### scaffold を使用して、`User`モデルと関連するビュー、コントローラを自動的に生成します。

```
docker-compose run --rm web bundle exec rails g scaffold user name:string address:string age:integer
```

各部分について説明します。

   - `docker-compose run --rm web` : `docker-compose.yml`に定義された`web`サービスを実行します。`--rm`オプションは、コマンド実行後にコンテナを自動的に削除することを指示します。
  
   - `bundle exec bin/rails g scaffold user name:string address:string age:integer` : Railsのscaffoldジェネレータを実行して`User`モデルと、それに対応するビュー、コントローラを生成します。生成される`User`モデルは`name`、`address`、`age`という3つの属性を持つことを指定しています。それぞれのデータ型は文字列、文字列、整数となります。

このコマンドを実行することで、ユーザーの作成、表示、更新、削除に必要なすべてのMVCコンポーネントが自動生成されます。生成されたファイルはマイグレーションファイル、モデルファイル、コントローラファイル、ビューファイルなどが含まれます。これにより、簡単にCRUD（作成、読み取り、更新、削除）機能を持つWebアプリケーションを構築できます。



### `development` 環境のデータベースに対してマイグレーションを実行する

  ```
  docker-compose run --rm web bundle exec rails db:migrate RAILS_ENV=development
  ```


各部分について説明します。

- `docker-compose run --rm web` : `docker-compose.yml`に定義された`web`サービスを実行します。`--rm`オプションは、コマンド実行後にコンテナを自動的に削除することを指示します。

- `bundle exec rails db:migrate RAILS_ENV=development` : Railsのマイグレーションシステムを用いて、`development` 環境のデータベースのスキーマを更新します。これは新たに作成されたマイグレーションファイル（今回は先ほど`rails g scaffold` コマンドで生成されたもの）に基づいた変更を適用します。`RAILS_ENV=development` はこのマイグレーションを開発環境のデータベースに対して実行することを指定しています。

このコマンドを実行することで、新しく生成されたマイグレーションファイルによるデータベースのスキーマ変更を適用します。これにより、データベースがアプリケーションの最新の状態を反映できるようになります。

### `localhost:3000/users` にアクセスして動作確認
 `docker-compose up -d` でコンテナを起動したのち、ブラウザに `localhost:3000/users` と入力しアクセスしてください。
コンテナ起動直後はアクセスに時間がかかることがありますのでしばらくお待ちください。

以下の画像にような画面が表示されれば成功です！

![スクリーンショット 2023-06-06 12.57.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2550355/bae13272-fc46-80cf-1258-8ee3a6b9b235.png)




# 最後に

以上で、Docker上でRailsの環境を構築する手順が完了となります。

ここまで読んでいただきありがとうございました！！
ぜひイイね！をよろしくお願いします (*ᴗˬᴗ)⁾⁾
それではまた！(^_^)ﾉｼ