🐕

Rails7.0.2 + PostgreSQL14.3 開発環境(docker)を構築する

2022/08/21に公開

環境構築手順の記録

開発環境

  • 作業PC: Apple M1 Pro
  • Rails: 7.0.2
  • Ruby: 3.1.1
  • PostgreSQL: 14.3

ゴール

ブラウザに http://localhost:3000 で初期画面にアクセスできること。

ディレクトリ階層

プロジェクトルート
├── data
├── docker-compose.yml
├── web
└── .env

手順1: 新規プロジェクトを作成する

ソースコード

.env
DB_HOST=db # データベースコンテナのサービス名
DB_USER=user # 任意
DB_PASSWORD=pass # 任意
docker-compose.yml
version: '3'
services:
 db:
   image: postgres:14.3
   ports:
     - 5432:5432
   volumes:
     - ./data:/var/lib/postgresql/data
   environment:
     POSTGRES_USER: ${DB_USER}
     POSTGRES_PASSWORD: ${DB_PASSWORD}
   restart: always

 web:
   build: 
     context: web
     dockerfile: Dockerfile
   command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
   volumes:
     - ./web:/app
   environment:
     DB_HOST: ${DB_HOST}
     DB_USER: ${DB_USER}
     DB_PASSWORD: ${DB_PASSWORD}
     EDITOR: vim
     RAILS_ENV: development
   ports:
     - "3000:3000"
   depends_on:
     - db
web/Dockerfile
# gemインストールのみに使用
FROM ruby:3.1.1-alpine as builder

ENV ROOT="/app"
ENV LANG=C.UTF-8
ENV TZ=Asia/Tokyo

WORKDIR ${ROOT}

COPY Gemfile Gemfile.lock ${ROOT}

RUN apk add \
   alpine-sdk \
   build-base \
   postgresql-dev \
   postgresql-client \
   tzdata \
   git

# M1のRails(Docker環境)起動時にnokogiriがLoadErrorとなる問題の解決方法
RUN apk add --no-cache gcompat

RUN gem install bundler && bundle install
web/Gemfile
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby "3.1.1"

# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
gem "rails", "~> 7.0.2", ">= 7.0.2.3"
web/Gemfile.lock
# (空ファイル)

コンテナをビルドする

$ cd プロジェクトルート
$ docker-compose build

rails newする

$ docker-compose run --rm web bundle exec rails _7.0.2_ new . -d postgresql -f
  • webディレクトリにrailsファイルが一式生成されます。

手順2: コンテナイメージを軽量化する

Dockerfileを編集

web/Dockerfile
# gemインストールのみに使用
FROM ruby:3.1.1-alpine as builder

ENV ROOT="/app"
ENV LANG=C.UTF-8
ENV TZ=Asia/Tokyo

WORKDIR ${ROOT}

COPY Gemfile Gemfile.lock ${ROOT}

RUN apk add \
    alpine-sdk \
    build-base \
    postgresql-dev \
    postgresql-client \
    tzdata \
    git

# M1のRails(Docker環境)起動時にnokogiriがLoadErrorとなる問題の解決方法
RUN apk add --no-cache gcompat

RUN gem install bundler && bundle install

# マルチステージビルド
FROM ruby:3.1.1-alpine AS runner

ENV ROOT="/app"
ENV LANG=C.UTF-8
ENV TZ=Asia/Tokyo

WORKDIR ${ROOT}

RUN apk update && \
    apk add \
        postgresql-dev \
        tzdata \
        bash \
        gcompat \
        vim

RUN apk add --no-cache nodejs

COPY --from=builder /usr/local/bundle /usr/local/bundle
COPY . ${ROOT}
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.1.1-alpine as builderステージはgemインストールのみに使用します

  • 1個目のbuilderステージの責務は bundle install を通すだけ
  • 2個目のrunnerステージ(実際の起動用)では --from から1個目のステージを指定してライブラリをコピーする

Gemfileを編集

gem "nokogiri" を1行追加するだけ。

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

ruby "3.1.1"

# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
gem "rails", "~> 7.0.3", ">= 7.0.3.1"

# The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
gem "sprockets-rails"

# Use postgresql as the database for Active Record
gem "pg", "~> 1.1"

# Use the Puma web server [https://github.com/puma/puma]
gem "puma", "~> 5.0"

# Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]
gem "importmap-rails"

# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
gem "turbo-rails"

# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
gem "stimulus-rails"

# Build JSON APIs with ease [https://github.com/rails/jbuilder]
gem "jbuilder"

gem "nokogiri"

# Use Redis adapter to run Action Cable in production
# gem "redis", "~> 4.0"

# Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis]
# gem "kredis"

# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
# gem "bcrypt", "~> 3.1.7"

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ]

# Reduces boot times through caching; required in config/boot.rb
gem "bootsnap", require: false

# Use Sass to process CSS
# gem "sassc-rails"

# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
# gem "image_processing", "~> 1.2"

group :development, :test do
  # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
  gem "debug", platforms: %i[ mri mingw x64_mingw ]
end

group :development do
  # Use console on exceptions pages [https://github.com/rails/web-console]
  gem "web-console"

  # Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler]
  # gem "rack-mini-profiler"

  # Speed up commands on slow machines / big apps [https://github.com/rails/spring]
  # gem "spring"
end

group :test do
  # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing]
  gem "capybara"
  gem "selenium-webdriver"
  gem "webdrivers"
end
web/entrypoint.sh
#!/bin/bash
set -e

rm -f /app/tmp/pids/server.pid
exec "$@"

コンテナイメージ再ビルドする

$ docker-compose build

手順3: rails を起動する

web/config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: <%= ENV["DB_HOST"] %>
  username: <%= ENV["DB_USER"] %>
  password: <%= ENV["DB_PASSWORD"] %>

development:
  <<: *default
  database: sample_development # 自分のデータベース名

test:
  <<: *default
  database: sample_test # 自分のデータベース名

production:
  <<: *default
  database: sample_production # 自分のデータベース名

DBを作成する

$ docker-compose run --rm  web bin/rails db:create 

コンテナを起動する

$ docker-compose up -d

http://localhost:3000にアクセスする

Railsの初期画面が表示されれば成功

もし、マイグレーションファイルがある場合

DB削除 + 作成 + マイグレーションファイル最初から実行 のコマンド

$ docker-compose run web bin/rails db:migrate:reset

Discussion