📌

Rails API + Postgresql の環境を Docker で構築する

2024/01/10に公開

Docker を用いて、Ruby on Rails API モードの開発環境の構築を行っていきます。
サンプル API を作成し、疎通確認するところまでやります。DB は作成しますがこの記事では使いません。

サンプルプロジェクト

https://github.com/ndjndj/playground/tree/main/rails

ディレクトリ構造

こんな感じでプロジェクトディレクトリに空のファイル群を作成しておきます。

.
├─ compose.yml
└─ rails
    ├─ Dockerfile
    ├─ Gemfile
    ├─ Gemfile.lock
    └─ entrypoint.sh

compose.yml などの準備

compose.yml で、postgres を使用した API を作成する別記事を公開する関係でデータベースに postgres を使用していますが、任意で大丈夫です。
Gemfile.lock は空のままで大丈夫です。
entrypoint.sh には、サーバーのプロセスが残っている場合、新たにサーバーを起動できないため、それを防ぐために起動時にプロセスをいったん削除するコマンドが記述されています。

compose.yml
version: '3'
services: 
  db: 
    container_name: postgres-sample
    image: postgres:16.0
    ports: 
      - "5432:5432"
    volumes: 
      - pg-data:/var/lib/postgresql/data
    environment: 
      - POSTGRES_DATABASE=postgres 
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password 
      - POSTGRES_ROOT_PASSWORD=root
  api: 
    container_name: api-sample
    build: 
      context: ./rails
    command: bash -c "rails s -b '0.0.0.0'"
    volumes:
      - ./rails:/usr/src/app
    ports: 
      - 3000:3000
    depends_on:
      - db 
    tty: true 
    stdin_open: true
volumes: 
  pg-data:
  bin: 
    driver: local
Dockerfile
FROM ruby:3.3.0
RUN apt-get update -qq && apt-get install -y vim 

RUN mkdir /usr/src/app 
WORKDIR /usr/src/app
COPY Gemfile /usr/src/app/Gemfile 
COPY Gemfile.lock /usr/src/app/Gemfile.lock 

RUN gem update --system 
RUN bundle update --bundler 

RUN bundle install 
COPY . /usr/src/app 

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh 
ENTRYPOINT ["entrypoint.sh"]
Gemfile
source "https://rubygems.org"
git_source(:github) {|repo| "https://github.com/#{repo}.git" }

ruby "3.3.0"

gem "rails", "~> 7.1.2"
entrypoint.sh
#!/bin/bash
set -e

rm -f /usr/src/app/tmp/pids/server.pid 

exec "$@"

Rails アプリの作成

下記コマンドを実行して、Rails アプリケーションを作成します。

docker compose run --rm api rails new . --skip --database=postgresql --api --skip-bundle

各オプションについて

各オプションやその他のオプションについてはこちらから確認することができます。

オプション 説明
. ディレクトリ直下にプロジェクトを作成
--force ファイルが存在する場合上書き
-skip ファイルが存在する場合スキップ
--database データベースを指定
--api API のみでアプリを作成
--skip-bundle bundle install をスキップ

Gemfile, database.yml を書き換える

以下のように Gemfile を書き換えます。
また、config/database.yml も作成した環境に合わせて書き換えます。

Gemfile
source "https://rubygems.org"
git_source(:github) {|repo| "https://github.com/#{repo}.git" }

ruby "3.3.0"

gem "bootsnap", require: false

gem "pg", "~> 1.1"

gem "puma", "~> 6.4.0"

gem "rails", "~> 7.1.2"

gem "tzinfo-data", platforms: %i[mingw mswin x64_mingw jruby]
config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: postgres
  password: password 
  host: db
  port: 5432

development:
  <<: *default
  database: postgres_dev
  password: password

test:
  <<: *default
  database: postgres_test
  password: password

gem をインストールする

下記コマンドを実行して、gem をインストールします。

docker compose run --rm api bundle install

Docker コンテナを立ち上げる

コンテナをビルドして立ち上げます。

docker compose build --no-cache
docker compose up -d

Postgresql の DB を作成する

現状だと DB が存在しないため作成する必要があります。
rails コンテナ環境に入ります。

docker compose exec api /bin/bash

rails コンテナ内で db:create して DB を作成します。

rails db:create

起動確認

下記にアクセスし、Rails が動作していることを確認します。

localhost:3000

サンプル API を作成し、動作確認

簡易的な JSON を返すサンプル API を作成してみます。
rails コンテナ内で下記コマンドを実行します。

コントローラーの作成

下記のようにコントローラーを実装します。

rails g controller status
status_controller.rb
class StatusController < ApplicationController
  def index
    render json: {message: "available."}, status: :ok
  end
end

routes.rb の設定

route を設定します。

config/routes.rb
Rails.application.routes.draw do
  get "status", to: "status#index"
end

疎通確認

上記通りの実装なら、下記 URL にアクセスします。
レスポンスが返ってくれば OK です。

localhost:3000/status

レスポンス

{"message":"available."}

さいごに

postgresql を利用する場合は、rails db:create する必要があることに気づかずちょいつまづいてしまいました。

参考

https://zenn.dev/hs7/articles/2cc4d67650ba69
https://railsdoc.com/page/rails_new
https://techguy10308blog.netlify.app/ja/20200510/

Discussion