Dockerを使った環境構築（Ruby on Rails/ PostgresSQL）

# 概要

プロジェクト参画メンバーの環境構築を簡単にするDockerという技術は
現在、Web開発の現場におけるデファクトスタンダードといっても過言ではありません。

とくにバックエンド領域を担当するエンジニアは、ほぼ確実にDockerを使用して開発を進めます。

今回は、入門エンジニアのポートフォリオの定番である
「Ruby on Rails」を使用したプロジェクトのDocker化について解説をしたいと思います。

注意：今回の記事では、Dockerの基礎概念や用語の詳細については述べません。
基礎用語については以下のサイトが非常に参考になりますので、一読をおすすめします。

https://zenn.dev/suzuki_hoge/books/2022-03-docker-practice-8ae36c33424b59

# プロジェクトのDocker化の流れ
Dockerを使用したRailsプロジェクトの立ち上げについての大きな流れは以下になります。

1. Dockerfile作成
2. docker-compose.yml
3. database.yml（rails独自設定）

最終的な完成版は以下になります。

https://github.com/umedanaoyuki/rails-docker

| 言語・フレームワーク | バージョン |
| -------------------- | ---------- |
| Ruby                 | 3.2.2      |
| Ruby on rails        | 7.0.6      |
| PostgresSQL          | 12         |


# 1. Dockerfile

`Dockerfile`にはコンテナの中身を記載します。
今回記載する内容は以下の内容になります。

・Rubyを使用
・Railsをコンテナの中で動かすためのパッケージをインストールする
・立ち上げたコンテナの中に「/rails-docker」というディレクトリを作成する
・上記のディレクトリの中にGemfileをコピーして、Gemをインストールする

上記の内容を`Dockerfile`にすると以下のようになります。


```Dockerfile
# Ruby3.2.2をインストール
FROM ruby:3.2.2

# Ruby on Railsを動かすためのパッケージ
RUN apt-get update -qq && apt-get install -y \
  build-essential \
  libpq-dev \
  nodejs \
  postgresql-client \
  yarn

# コンテナの中にディレクトリを作成
WORKDIR /rails-docker

# Gemifileをコンテナの中の指定のディレクトリにコピー
COPY Gemfile Gemfile.lock /rails-docker/

# コピーしたGemをインストールする
RUN bundle install

```


# 2. docker-compose.ymlを作成する

今回は２つのアプリケーション（WebとDB）を作成して、連携させます。

Dockerの基本的な考え方「１つのコンテナには１つのアプリケーション」という原則にしたがってWebコンテナとDBコンテナの２つを作成します。

複数のコンテナを作成して、連携をさせる場合には
`docker-compose.yml`を作成して コンテナを起動するときの挙動や、複数のコンテナとの関係性を記載します。


こちらが`docker-compose.yml`の中身になります。

重要なポイントは３つあります。
（１）Webコンテナを立ち上げる記載をします。
（２）DBコンテナを立ち上げる記載をします。
（３）DBコンテナの中のDBの情報が、コンテナを削除してもなくならないように`Docker Volume`という機能を使用します。


```docker-compose.yml

version: "3"

# 今回はdb-dataという名前でDocker volumeを作成します。・・・・（３）
volumes:
  db-data:

# 今回は2つのコンテナを立上げます（Web/DB）
services:
  # Webコンテナ・・・・（１）
  web:
    
    # 自身で作成したDockerfileからimageをビルドします。  
    build: .
    
    # コンテナを起動した際に実行したいコマンドになります。  
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails db:migrate && bundle exec rails s -p 3000 -b '0.0.0.0'"

    # コンテナが起動するポートです。
    ports:
      - 3000:3000
      
    # コンテナ内で作成したデータを永続化するための場所を指定します。
    volumes:
      - .:/rails-docker/

    # 環境変数
    environment:
      - "DATABASE_PASSWORD=postgres"
      
    tty: true
    stdin_open: true
    
    # DBコンテナが立ち上がったら、Webコンテナを起動します。
    depends_on:
      - db
      
    # WebコンテナからDBコンテナにアクセスします。
    links:
      - db

  # DBコンテナ・・・（２）
  db:
    # すでにDocker Hub上に存在するpostgres12のdocker imageを使用するため、今回はbuildではなく、imageを使用します。  
    image: postgres:12

    # Postgresのコンテナの中において、情報が保管されるディレクトリを作成します。
    # 今回は docker volumeという機能を利用して その中にdb-dataという領域を確保し、その領域とPostgresのコンテナをマウントさせます。（volumeを使用しない場合、コンテナを削除してしまうと、データが消えてしまいます）
    volumes:
      - db-data:/var/lib/postgresql/data

    environment:
      - "POSTGRES_USER=postgres"
      - "POSTGRES_PASSWORD=postgres"

```


# 3. database.ymlの編集

こちらはRails特有の設定の書き方になりますので、今回は解説を省略します。

```database.yml
# PostgreSQL. Versions 9.3 and up are supported.
#
# Install the pg driver:
#   gem install pg
# On macOS with Homebrew:
#   gem install pg -- --with-pg-config=/usr/local/bin/pg_config
# On macOS with MacPorts:
#   gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
# On Windows:
#   gem install pg
#       Choose the win32 build.
#       Install PostgreSQL and put its /bin directory on your path.
#
# Configure Using Gemfile
# gem "pg"
#
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  user: postgres
  port: 5432
  password: <%= ENV.fetch("DATABASE_PASSWORD") %>
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: myapp_development

  # The specified database role being used to connect to postgres.
  # To create additional roles in postgres see `$ createuser --help`.
  # When left blank, postgres will use the default role. This is
  # the same name as the operating system user running Rails.
  #username: myapp

  # The password associated with the postgres role (username).
  #password:

  # Connect on a TCP socket. Omitted by default since the client uses a
  # domain socket that doesn't need configuration. Windows does not have
  # domain sockets, so uncomment these lines.
  #host: localhost

  # The TCP port the server listens on. Defaults to 5432.
  # If your server runs on a different port number, change accordingly.
  #port: 5432

  # Schema search path. The server defaults to $user,public
  #schema_search_path: myapp,sharedapp,public

  # Minimum log levels, in increasing order:
  #   debug5, debug4, debug3, debug2, debug1,
  #   log, notice, warning, error, fatal, and panic
  # Defaults to warning.
  #min_messages: notice

# 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: myapp_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="postgres://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: myapp_production
  username: myapp
  password: <%= ENV["MYAPP_DATABASE_PASSWORD"] %>

```

以下が最終的な完成版になります。
このリポジトリに、起動手順を記載しましたので、`git clone`をして確認してみてください。

https://github.com/umedanaoyuki/rails-docker/tree/main