DockerでRuby on Railsの環境構築をやってみた

# この記事の内容について
　こんにちは！プログラミングのオンラインスクールで学習をしている初学者です。日々の学習の復習としてチーム開発を行いました！その際にDockerによる開発環境の構築を行ったので、アプトプットとしてまとめます！
　初学者なので間違い等があればごしていただけると幸いです。

# プロジェクトディレクトリの作成
まず、初めに以下のコマンドを実行し、ディレクトリを作成しました！
```
mkdir team_development_app
cd team_development_app
```

# 必要ファイルの作成
次にDockerに必要なファイルを作成しました。参考URLの記事やカリキュラムのコードなどを参考にファイルを作成しましたが、わからない部分はChatGPTで質問しながら、メモを残した形になります。(こちらも理解が追いついていない部分が多いです。)

* dockerfile
``` Dockerfile:dockerfile
# ベースとなるDockerイメージを選択(ruby 3.1.4を使用する)
FROM ruby:3.1.4

# 言語設定を指定するための環境変数
# ENV LANG C.UTF-8(汎用性があり、国際化などの対応化)
# ENV LANG=ja_JP.UTF-8(一般的な日本語のアプリケーションで推奨されている)
ENV LANG=ja_JP.UTF-8

# コンテナ内のシステム時刻を日本標準時に設定
ENV TZ Asia/Tokyo

# Gemのインストールに必要なライブラリをインストール(Rails7では不要？)
# RUN \
# Node.jsをインストールするために実行(rails7を使用する場合は不要？)
# curl -sL https://deb.nodesource.com/setup_19.x | bash - \
# Yarnパッケージマネージャーをインストールするために必要(rails7を使用する場合は不要？)
# && wget --quiet -O - /tmp/pubkey.gpg https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
# Yarnパッケージを公式のリポジトリから取得できるようにする(rails7を使用する場合は不要？)
# && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
# パッケージリストの更新
# apt-get update -qq \
# ビルド / DB / JavaScriptなどで必要なものをインストール(rails7を使用する場合は"node.js / yarn"は不要)
# && apt-get install -y build-essential libpq-dev nodejs yarn
# && apt-get install -y build-essential libpq-dev

# アプリケーションのルートディレクトリを作成
RUN mkdir /team_development_app

# 作業ディレクトリの変更(以降のコマンドが指定のディレクトリで使用される)
WORKDIR /team_development_app

# Bundlerのバージョン3.2.4をインストール
# RUN gem install bundler:3.2.4

# ホストマシンの"Gemfile/Gemfile.lock"を作業ディレクトリにコピー
COPY Gemfile /team_development_app/Gemfile
COPY Gemfile.lock /team_development_app/Gemfile.lock

# RubyGems / Bundlerのアップデート
RUN gem update --system
RUN bundle update --bundler

# ホストマシンの"yarn.lock"を作業ディレクトリにコピー
# 該当ファイルが存在しないため省略
# COPY yarn.lock /v3_basic_rails_basic/yarn.lock

# Gemfileからgem依存関係をインストール
RUN bundle install

# Yarnを使用してJavaScriptパッケージの依存関係をインストール
# 該当ファイルが存在しないため省略
# RUN yarn install

# カレントディレクトリのアプリケーションコード全体をコンテナの作業ディレクトリにコピー
COPY . /team_development_app

# コンテナ起動時にシェルスクリプトを実行する
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

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

* docker-compose.yml
```YAML:docker-compose.yml
# Docker Composeのバージョン指定
version: '3'

# サービス(コンテナ)の定義
services:
  db:
    image: mysql:8.1
    platform: linux/amd64
    environment:
      TZ: Asia/Tokyo
      MYSQL_DATABASE: root
      MYSQL_ROOT_PASSWORD: password
    volumes:
      - mysql_data:/var/lib/mysql
    ports:
      - 3306:3306
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    container_name: team_development_app_container
    tty: true
    stdin_open: true
    volumes:
      # ホストのカレントディレクトリをコンテナの作業ディレクトリにマウント
      - .:/team_development_app
      # gemを保存するボリュームをマウント
      - bundle_data:/usr/local/bundle:cached
    environment:
      TZ: Asia/Tokyo
      SELENIUM_DRIVER_URL: http://chrome:4444/wd/hub
    ports:
      - "3000:3000"
    depends_on:
      - db
      - chrome
  # ブラウザ（Selenium用）のコンテナ
  chrome:
    image: seleniarm/standalone-chromium:latest
    ports:
      - 4444:4444
# ボリュームの定義
volumes:
  mysql_data:
  bundle_data:

# ボリュームのマウントとは？
# アプリケーションのデータ管理や永続化、コンテナ間のデータ共有などで使用する
# 特に、データベース、設定ファイル、ログファイル、アプリケーションコードなどを永続化するために頻繁に利用される。
```

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

下記のGemfile.lockも作成しておく
```
touch Gemfile.lock
```

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

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
```

# プロジェクトの作成
下記コマンドを実行していけば、環境構築が完了する。

* プロジェクトの作成
```
docker-compose run web rails new . --force --no-deps --database=mysql
```
* DB接続の設定
```YAML:config/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

development:
  <<: *default
  database: team_development_app_development

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: team_development_app_test

# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password or a full connection URL as an environment
# variable when you boot the app. For example:
#
#   DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase"
#
# If the connection URL is provided in the special DATABASE_URL environment
# variable, Rails will automatically merge its configuration values on top of
# the values provided in this file. Alternatively, you can specify a connection
# URL environment variable explicitly:
#
#   production:
#     url: <%= ENV["MY_APP_DATABASE_URL"] %>
#
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full overview on how database connection configuration can be specified.
#
production:
  <<: *default
  database: team_development_app_production
  username: team_development_app
  password: <%= ENV["TEAM_DEVELOPMENT_APP_DATABASE_PASSWORD"] %>

```
* DB作成
```
docker-compose run web rails db:create
```
* イメージの起動
```
docker-compose up
```

# 参考文献

この記事は以下の情報を参考にして執筆しました。

- [Rails 7 + MySQLの環境構築をDocker composeで作る](https://qiita.com/croquette0212/items/7b99d9339fd773ddf20b)