Dockerを使ってRuby on Railsの環境構築をしてみた

# はじめに
DockerもRuby on Railsもどちらも扱ったことがなかったので、
まとめて学習できれば良いなと思ったのがきっかけです。
今回は簡単な画面表示までをやっていきます。
※Windows環境です

# 必要なファイルの用意
docker-sampleというディレクトリを作成し、この中で作業していきます。
まず、以下4つの空ファイルをディレクトリ直下に作成します。
Dockerfile
docker-compose.yml
Gemfile
Gemfile.lock
entrypoint.sh

````
docker-sample/
　　　├─ Dockerfile
　　　├─ docker-compose.yml
　　　├─ Gemfile
　　　├─ Gemfile.lock
　　　└─ entrypoint.shDockerfile
````
各ファイルの中身はこの後設定していきます。

# Dockerfileの設定
DockerfileとはDockerイメージを作成するための設計書のようなものです。
今回は以下の内容で作成します。

````
FROM ruby:3.0

RUN apt update -qq && apt install -y postgresql-client
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]
````
|設定値|説明|
|---|---|
|FROM ruby:3.0|ruby3.0のイメージを使用します|
|apt install -y postgresql-client|DBとしてpostgresqlを使用します|
|RUN bundle install|gemfile.lockを元にgemのインストールを行います(後述)|
|ENTRYPOINT ["entrypoint.sh"]|コンテナ実行時に、コンテナに対し実行したいコマンドをシェルにまとめている|
|EXPOSE 3000|コンテナ側のポートを3000に設定します|
|CMD ["rails", "server", "-b", "0.0.0.0"]|コンテナ実行時のコマンドです。Railsサーバーの起動コマンドとして「rails server -b 0.0.0.0」を実行します|

# docker-compose.ymlの設定
docker-compose.ymlとはコンテナ起動時の設定等を定義するためのファイルです。
今回は以下の内容で作成します。
````
version: "3.9"
services:
  db:
    image: postgres
    ports:
      - "5432:5432"
    volumes:
      - ./tmp/db:/var/lib/postgresql
    environment:
      POSTGRES_USER: postgres
      POSTGRES_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
````
|設定|説明|
|---|---|
|version|Compose ファイルの書式のバージョンです|
|command|Dockerを起動する際に実行するコマンドを書きます。ここではserver.pidの削除と、サーバー立ち上げをしています。|
|volumes|ローカルディレクトリのマウントです。docker-sample内のプログラムがコンテナの/myappにも作られます。|
|ports|ホスト側ポート:コンテナ側ポート|
|depends_on|サービス間の依存関係を指定しています。これでwebより先にdbが立ち上がるという順番になります。よって、dbが立ち上がらなければwebも立ち上がらないという依存関係になります。|
|tty|docker runコマンドの -t オプションと同じで、コンテナ内での操作結果がコンソール上に出力されるようになります。|
|stdin_open|docker runコマンドの -i オプションと同じで、エラー等がコンソール上に出力されるようになります。|

※今回はRubyでデバックもできるようにしたいのでttyとstdin_openの設定が必要になります。

# Gemfileの設定
Gemfileとはgemが記述されているファイルのことです。
gemはRubyのライブラリのことです。
````
source 'https://rubygems.org'
gem 'rails', '~> 7.0.4'
````
|設定|説明|
|---|---|
|source|gemのコードの取得場所を示しています。|
|gem|Railsのバージョンを示しています。|

# Gemfile.lockの設定
Gemfile.lockとはGemfileを元にインストールされた、gemの一覧とバージョンが記載されたファイルです。
最初は空で構いません。
````
````

# entrypoint.shの設定
entrypoint.sh初回起動時のみに処理したい内容を記述するシェルスクリプトです。
Windows環境の場合、改行コードをLFにしてください。CRLFだと動作しません。

````
#!/bin/bash
set -e

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

exec "$@"
````

# コンテナーイメージのビルド
ファイルが用意できたら、イメージのビルドを行います。
````
docker-compose build
````

# Railsプロジェクト生成
 docker-compose コマンドを使って rails new を実行し、 Rails プロジェクトを作成します。
````
docker-compose run web rails new . --force --no-deps --database=postgresql
````
|設定|説明|
|---|---|
|--force|既存のGemfileを上書きするためのオプション|
|--no-deps|リンクしたサービスを起動しない|
|--database=postgresql|DBにpostgresqlを指定|

プロジェクト生成後、config/database.ymlに以下記述を追加してください
config/database.ymlに以下を追加	
````
	default: &default
	  adapter: postgresql
	  encoding: unicode
	  host: db　　　　　　★追加
	  username: postgres　★追加
	  password: password　★追加
	  pool: 5
````


# データベース作成
次にDBを生成します。
````
docker-compose run web rails db:create
````
成功した場合、以下のような表示がでるはずです
````
[+] Running 1/0
 - Container docker-sample-db-1  Running                                                                          0.0s
Created database 'myapp_development'
Created database 'myapp_test'
````

もし成功しない場合、以下コマンドお試しください。
````
docker-compose build --no-cache
````

# Dockerを起動
以下コマンドで起動します。
````
docker-compose up -d
````
以下のように表示されれば成功です。
````
[+] Running 2/2
 - Container docker-sample-db-1   Started                                                                         1.1s
 - Container docker-sample-web-1  Started                                                                         2.2s
````

これで、http://localhost:3000/ に接続し、Rails画面が表示されれば確認OKです。

# Dockerを起動がうまくできない場合
この手順で環境構築する場合、たまに起動に失敗することがあります。
その場合、DockerDesktop上でコンテナを起動してみたり、noneと表示されているイメージやコンテナを削除するとうまくいきます。

# 参考サイト
https://mseeeen.msen.jp/rails-docker/
https://qiita.com/lasershow/items/1a048d03ddaaba98171e