Ruby on Railsコンテナの作成方法について

## はじめに
今回はDockerを使ったRailsのコンテナ作成を行なっていきたいと思います。

## コンテナとは
そもそも`コンテナ`とはなんなのか？
一言で言うと`アプリとファイルシステムを隔離する特殊なプロセス`のことです。また、ここでいう`プロセス`とは、OS上で動作している1つ1つの処理のことで、まあ要するに`動作中の個々のプログラム`のことだと思ってください。
アプリとファイルシステムを隔離するということは、1つの物理マシンの中で稼働しているにも関わらず、`そのプロセスだけが別マシンで動作している状態になる`ということです。
コンテナを使うには、コンテナの作成および実行を行うソフトウェアが必要になってきます。そこで用いられるのが`Docker`です。
コンテナの設計図となる「イメージ」を共有できる場所もあり、また、それを利用して短時間でコンテナの作成を行ったりと一種のエコシステムを形成しています。

その他コンテナ・Dockerについての詳細を知りたい方は[こちら](https://o2mamiblog.com/docker-beginner-1/)の記事を参考にしてください。初心者の自分でも理解できるくらいわかりやすくまとめられていました！

## Ruby on Rails とは
Ruby on Rails(以降、Rails)とはRubyでWebアプリを作るためのフレームワークです。Railsを使用するためにはデータベースが必要です。今回はMariaDBを使用していきます。

## Railsの動作および手順
RailsとMariaDBを組み合わせて使用するには以下の手順が必要です。
1. Rubyをインストール
2. Railsの動作に必要なライブラリ(yarnやNode.js)をインストール
3. Gemfile、Gemfile.lockを作成
4. `bundle install`コマンドを実行してRailsをインストール
5. `rails new . --force --no-deps --database=mysql`コマンドを実行してRailsのプロジェクトを作成
6. 　作成したプロジェクト内のdatabase.ymlを、MariaDBに接続する設定に変更
7. 　`rake db:create`コマンドを実行して、データベースを作成 
8. 　`rails server`コマンドを実行して、Webサーバーを実行

## 使用するイメージと設定ファイル
ソフトウェアをインストールしたイメージが必要なので、Dockerfileを作成していきます。
イメージはコンテナの設計図になります。このDockerイメージを元にし、コンテナが作成されていきます。
 ![Dockerイメージ](https://o2mamiblog.com/wp-content/uploads/2022/07/Docker-1_page-0005.jpg)
> 上図からも分かるように取得したイメージはDockerホスト内のキャッシュと呼ばれるローカルイメージに保存されます。そのため、一度取得したイメージはキャッシュから取得することができるようになります。

https://o2mamiblog.com/docker-beginner-1/

この仕組みによって、コンテナを素早く起動することができます。
イメージは、Rubyの公式イメージを使用します。

|    イメージ    |                    公式URL                     |
|----------------|------------------------------------------------|
| Ruby           | [https://hub.docker.com/_/ruby](https://hub.docker.com/_/ruby)       |
| MariaDB        | [https://hub.docker.com/_/mariadb](https://hub.docker.com/_/mariadb) |


これらの公式URLにアクセスすると、それぞれのDockerイメージの詳細情報を確認できます。

また、**Dockerfile**と**docker-compose.yaml**を使用することで、アプリケーションの開発やデプロイメントを簡素化し、環境の再現性や可搬性を高めることができます。

- **Dockerfile**は、Dockerイメージを作成するための設定ファイルです。Dockerfileには、ベースイメージの指定や必要なパッケージのインストール、アプリケーションのソースコードのコピーなどが記述されます。Dockerfileをビルドすることで、Dockerイメージが作成されます。

- **docker-compose.yaml**は、複数のコンテナを定義し、それらを連携させるための設定ファイルです。例えば、データベースコンテナとアプリケーションコンテナの関係性やボリュームのマウントなどがdocker-compose.yamlに記述されます。docker-composeコマンドを使用して、docker-compose.yamlをもとに複数のコンテナを一括管理することができます。

そしたら、Railsの動作に必要な手順を落とし込んだ、Docdkefileとcompse.yamlを作成していきます。
```
myapp
  |-- Dockerfile
  |-- compose.yaml
  |-- Gemfile
  |-- Gemfile.lock
```
```dockerfile: Dockerfile
FROM ruby:3.2.2
# ベースにするイメージを指定

RUN apt-get update -qq

RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && apt-get install -y nodejs
RUN npm install --global yarn
# Railsのインストールや必要なパッケージをインストール

WORKDIR /samplerails
# 作成した/samplerailsディレクトリを作業用ディレクトリとして設定

COPY Gemfile Gemfile.lock /samplerails/
# ローカルの Gemfile と Gemfile.lock をコンテナ内のsamplerails配下にコピー

RUN bundle install
# コンテナ内にコピーした Gemfile の bundle install

CMD ["rails", "server", "-b", "0.0.0.0"]
# Dockerイメージ内のコンテナが起動されたときに自動的に実行されるデフォルトのコマンドを指定するためのDockerfileの命令
```
```yaml: compose.yaml
services:
  db: # MariaDBコンテナ
    image: mariadb:10.7 
    environment:
      MARIADB_ROOT_PASSWORD: password
    volumes:
      - db-data:/var/lib/mysql # ボリューム

  web: # Railsコンテナ
    build: .
    depends_on:
      - db
    environment:
      DATABASE_PASSWORD: password
    ports:
      - "3000:3000" #　ポート番号
    volumes:
      - .:/samplerails # ボリューム

volumes:
  db-data:

```

イメージにソフトウェアをインストールするために、DockerFileに`RUN apt-get~`コマンドを記載しています。

また、Railsコンテナを作成するためには**Gemfil**eと**Gemfile.lock**が必要になります。
**Gemfile**と**Gemfile.lock**は、Rubyプロジェクトで使用するGem（Rubyのパッケージやライブラリ）の依存関係を管理するためのファイルです。それぞれについては以下のようなものになっています。

- **Gemfile**は、プロジェクトのルートディレクトリに配置されるファイルで、Gemの名前とバージョン制約を記述します。Gemfileは開発者が手動で編集し、プロジェクトが依存するGemを定義します。

- **Gemfile.lock**は、実際にインストールされたGemのバージョン情報を含む自動生成されるファイルです。Gemfile.lockはBundlerによって管理され、プロジェクトの特定の環境における正確なGemのバージョンを保証します。Gemfile.lockは通常、バージョンの衝突や互換性の問題を防ぐために、共有されるかバージョン管理システムにコミットされます。

今回使用するGemfileとGemfile.lockは以下のようになっています。
```Gemfile: Gemfile
source 'https://rubygems.org'
gem "rails", "7.0.5"
```
```Gemfile.lock
```

## コンテナの作成準備
Railsを起動するためにはRailsプロジェクトそのものが必要です。プロジェクト作成後に設定ファイルを修正するためにも、まずは`docker compose run`コマンドでRailsプロジェクトを作成していきます。
```
% docker compose run --rm web rails new . --force --no-deps --database=mysql
```
を実行してください。
[![Image from Gyazo](https://i.gyazo.com/610b281825930b836b0d61d1516afee8.png)](https://gyazo.com/610b281825930b836b0d61d1516afee8)
ここで入力されている`rails new . --force --no-deps --database=mysql`は、Railsプロジェクトの新規作成コマンドです。

- `.`は、現在のディレクトリにRailsプロジェクトを作成することを意味します。
- `--force`は、既存のファイルを上書きする際に確認をスキップし、強制的に上書きします。
- `--no-deps`は、依存関係のインストールをスキップします。通常、Railsプロジェクトを作成する際には依存関係（Gemやライブラリ）が自動的にインストールされますが、このオプションを使用すると依存関係のインストールを行わずにプロジェクトを作成します。
- `--database=mysql`は、データベースの種類をMySQLに指定します。RailsプロジェクトはデフォルトでSQLiteを使用する設定になっていますが、このオプションを使用することでMySQLを使用するように設定されます。

以上のコマンドを実行すると、現在のディレクトリに新しいRailsプロジェクトが作成されます。作成されるプロジェクトには、MySQLを使用するための設定が含まれています。
[![Image from Gyazo](https://i.gyazo.com/98888afe0dde4e3e9a7dd41e95038086.png)](https://gyazo.com/98888afe0dde4e3e9a7dd41e95038086)

イメージを再度ビルドする必要があるので、`docker compose build`コマンドを実行します。
[![Image from Gyazo](https://i.gyazo.com/3798c9ed356f8a2e5c772d725a47c409.png)](https://gyazo.com/3798c9ed356f8a2e5c772d725a47c409)

次に、Railsの接続先をMariaDBのコンテナにするために作成された**database.yml**を開きます。
**database.yml**は**config**のフォルダー内にあります。
ファイルを開いたら、**default: &dafault**を以下の内容に変更します。
```yml: database.yml
# 一部省略
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: <%= ENV.fetch("DATABASE_PASSWORD") %> # 変更
  host: db # 変更 
  port: 3306 # 追加

development:
  <<: *default
  database: samplerails_development
```
## コンテナの作成 
ようやく準備が終わりましたね・・・
そしたら`docker compose up -d`コマンドを使用してコンテナを作成していきます。
`docker-compose up`コマンドとは、Docker Composeを使用して複数のコンテナを起動するためのコマンドです。
また、`docker-compose up -d`は通常の`docker-compose up`コマンドとは異なり、-dオプションを指定することでコンテナがデタッチドモード（バックグラウンド）で起動されます。つまり、コンテナのログは表示されず、コマンドプロンプトはすぐに利用可能になります。
具体的には以下のことが起きています。
1. docker-compose.ymlファイルの読み込みと構成の解析
2. 必要な場合には、Dockerイメージのビルド
3. 起動するコンテナの作成およびバックグラウンドでの開始
4. サービス間の依存関係の解決とネットワークの構成

まあ要するに続けて操作を行いたい場合は、-dオプションをつけておくのが無難でしょう。

では、`docker-compose up -d`を実行してみます。
[![Image from Gyazo](https://i.gyazo.com/393acaee6d9240ec5e119d62d0987689.jpg)](https://gyazo.com/393acaee6d9240ec5e119d62d0987689)

先ほども言いましたが、Railsを起動するには事前にデータベースを作成しておく必要があります。そこでRailsの用意されている`rake db:create`コマンドを実行します。
`docker compose exec web rake db:create`
[![Image from Gyazo](https://i.gyazo.com/d03ca74917cc44124fef9a8a3690b568.jpg)](https://gyazo.com/d03ca74917cc44124fef9a8a3690b568)

ここまでがコンテナの作成方法になります。お疲れ様でした！
最後にWebブラウザで接続確認をしてみましょう。
[![Image from Gyazo](https://i.gyazo.com/de36d920a82dfe4526bb477585f136b5.png)](https://gyazo.com/de36d920a82dfe4526bb477585f136b5)

きちんと表示されたでしょうか？
今回作成したコンテナのRailsプロジェクトは、初期状態のままなので、機能を追加したい場合はローカルのRailsプロジェクトに機能を追加していきましょう。

## まとめ
Dockerを使用してRailsアプリケーションを作成する手順を以下にまとめます。
1. プロジェクトディレクトリの作成
2. Dockerfileの作成
3. Gemfileの作成
4. Dockerイメージのビルド
5. Railsプロジェクトの作成
6. Docker Composeファイルの作成
7. Docker Composeを使用してアプリケーションを起動

## 最後に
今回はDockerを使ったRailsのコンテナ作成を行なっていきました。Docker自体使うことが初めてでカタカナ用語に苦戦しつつもなんとかなりましたね・・・😅
今後も開発をする際は積極的に活用していき、よりDockerへの理解を深められたらいいなと思います。
最後までお読みいただきありがとうございました。

## 引用文献
https://www.docker.com/

https://o2mamiblog.com/docker-beginner-1/

https://book.impress.co.jp/books/1121101138