Docker/Docker Composeを使ってサクッとRuby on Railsの環境構築(Rails6.x)

> 2022/03/03 
  Ruby, Railsのバージョンを更新しました。
  Ruby: 2.6.5 => 3.1.1
  Rails: 5.2.4.2 => 6.1.3.1

# はじめに
書籍や動画、Qiita記事を参考にDocker, Docker-compose を使用してRuby on Railsの環境を構築することができたのでまとめました。

# 環境
- MacOS(Big Sur)
- Docker: 20.10.12
- Docker Compose: v2.2.3
- Ruby: 3.1.1
- Rails: 6.1.3.1

# ソースコード
下記GitHubにソースコードを公開しています。

GitHub
https://github.com/yodev21/docker_tutorial_rails

Makefileを作成しているので、とりあえず動作確認だけしたい場合は下記コマンドを実行することで環境を自動構築してくれます。

```shell
# Rails環境構築
git clone git@github.com:yodev21/docker_tutorial_rails.git
cd docker_tutorial_rails
make setup

# scaffold実行
# 別ターミナルで実行
docker-compose run web bin/rails g scaffold User name:string
docker-compose run web bin/rails db:migrate
```

# 構築手順
## ファイル作成

```shell
# Railsアプリ用ディレクトリ作成
mkdir rails_project

# rails_projectに移動
cd rails_project

# 必要ファイルの作成
touch Dockerfile
touch docker-compose.yml
touch Gemfile
touch Gemfile.lock
```

# 設定ファイル修正
- Dockerfile

```Dockerfile
# イメージ名にRubyの実行環境のイメージを指定
FROM ruby:3.1.1

# yarnパッケージ管理ツールをインストール
RUN 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

# パッケージのリストを更新しrailsの環境構築に必要なパッケージをインストール
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs yarn

# プロジェクト用のディレクトリを作成
RUN mkdir /myapp

# ワーキングディレクトリに設定
WORKDIR /myapp

# プロジェクトのディレクトリにコピー
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock

# bundle install実行
RUN bundle install

# ビルドコンテキストの内容を全てmyappにコピー
COPY . /myapp
```

- docker-compose.yml
```docker-compose.yml
version: '3'
services:
  db:
    # postgresのイメージを取得
    image: postgres
    environment:
      POSTGRES_USER: 'postgresql'
      POSTGRES_PASSWORD: 'postgresql-pass'
    restart: always
    volumes:
      - pgdatavol:/var/lib/postgresql/data
  web:
    # Dockerfileからイメージをビルドして使用
    build: .
    # コンテナ起動時に実行
    command: bash -c "rm -rf tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    # カレントディレクトリを/myappにバインドマウント
    volumes:
      - .:/myapp
    # 3000で公開して、コンテナの3000へ転送
    ports:
      - "3000:3000"
    # Webサービスを起動する前にdbサービスを起動
    depends_on:
      - db
    environment:
      WEBPACKER_DEV_SERVER_HOST: webpacker
  webpacker:
    build: .
    volumes:
      - .:/myapp
    command: ./bin/webpack-dev-server
    environment:
      WEBPACKER_DEV_SERVER_HOST: 0.0.0.0
    ports:
      - "3035:3035"
# データ永続化のためにpgdatabolのvolumeを作成し、postgresqlのデータ領域をマウント
volumes:
  pgdatavol:
```

- Gemfile
```Gemfile
source 'https://rubygems.org'
gem 'rails', '6.1.3.1'
```

- Gemfile.lock
※空ファイルで問題ないです。
```Gemfile.lock
```

## Railsアプリケーション作成

```zsh
# Railsアプリケーションの作成
docker-compose run web rails new . --force --database=postgresql

# イメージのビルド
docker-compose build
```

## railsプロジェクトに使用するデータベースの設定ファイルを修正

```config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  # -------- 追加 --------
  host: db
  username: postgresql
  password: postgresql-pass
  # -------- ここまで --------
```

## データベース作成コマンド

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

## Scaffoldにて簡易的なアプリケーション作成

```zsh
docker-compose run web bin/rails g scaffold User name:string
```

```zsh
docker-compose run web bin/rails db:migrate
```

## Railsアプリケーションの起動

```zsh
docker-compose up
# ※デタッチモード（バックグラウンド）で起動したい場合は -d オプションを追加します。
```

## アプリケーションの動作確認
下記URLからscaffoldコマンドで作成されたCRUDアプリケーションが動くか確認します。
http://localhost:3000/users


# 参考URL
[いまさらだけどDockerに入門したので分かりやすくまとめてみた](https://qiita.com/gold-kou/items/44860fbda1a34a001fc1#%E3%83%9B%E3%82%B9%E3%83%88%E5%9E%8B%E4%BB%AE%E6%83%B3%E5%8C%96)

[Dockerイメージとコンテナの削除方法](https://qiita.com/tifa2chan/items/e9aa408244687a63a0ae)

[Dockerコンテナの作成、起動〜停止まで](https://qiita.com/kooohei/items/0e788a2ce8c30f9dba53#5%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E5%81%9C%E6%AD%A2)

[Docker Compose + Railsでイメージ内でbundle installしているはずなのにgemが無いとエラーがでる。](https://qiita.com/hokita222/items/49f4ca54835e08fdd6b2)

[Dockerでコンテナ内にbundle installされない問題の解決法](https://fuqda.hatenablog.com/entry/2019/03/21/204118)