Help us understand the problem. What is going on with this article?

DockerでRailsチュートリアルのローカル開発環境構築(Rails 6 + PostgreSQL + Webpack)

(2020.10.28 更新: docker-compose.ymlのvolume最適化、build時間短縮)

はじめに

最新(2020.8.5現在)のRailsチュートリアルではRails 6が使用されており、
これに対応した開発環境構築をDockerでやってみたいと思います。

個人開発アプリの開発環境構築の際に、
私は新しいものが好きだから...とRails 6を導入しました。

ところが...このRails 6からJavaScriptのモジュールバンドラーにWebpackが導入されたことにより、
BootstrapやFontawesomeといったツールの導入、管理方法が変わるだけでなく、
そもそも環境構築の際もRails 5では必要ない手順が必要だったりと、
Rails 6とWebpackの壁に盛大にぶつかることとなりました...

せっかくなので、今回の試みを経て、知識、経験の整理定着を図りたいと思います。

また、実際にRailsチュートリアルを脱線しながら再走し、学びを深められたらと思っています。

関連記事

第一回(当記事)
DockerでRailsチュートリアルのローカル開発環境構築(Rails 6 + PostgreSQL + Webpack) - Qiita

第二回
DockerでRailsチュートリアルのローカル開発環境構築 - RSpec導入 & CircleCIでHerokuデプロイ- - Qiita

第3回
DockerでRailsチュートリアルのローカル開発環境構築 - WebpackでBootstrapとFont Awesomeを導入 - - Qiita

第4回
コンテナ上のデバッグ環境構築 - DockerでRailsチュートリアルのローカル開発環境構築 - - Qiita

個人開発アプリ
mdClip <オンラインmarkdownエディタ>

以前Rails 5の環境構築をDockerでやってみた記事
はじめてのDockerでRails開発環境構築 [NGINX + Rails 5 (puma) + PostgreSQL] - Qiita

環境

  • Mac OS (Mojave)
  • Docker for Mac
  • Ruby 2.6.3-alpine
  • Rails 6.0.3
  • PostgreSQL 11.0-alpine

構成ファイル

以下の5つのファイルをワークスペースに用意します
Dockerfile, docker-compose.yml, Gemfile, Gemfile.lock, entrypoint.sh

https://github.com/naokit-dev/sample_app_on_docker.git

git clone -b create-docker-files https://github.com/naokit-dev/sample_app_on_docker.git

Dockerfile

  • イメージの軽量化のため"alpine"を使用

  • nodejs, yarnはWebpack導入に必要

  • postgresqlだけでは駄目で、postgresql-devも必要

  • bundle installの-j4オプションでbundle installが高速化される

  • bundle install後、不要ファイル削除はイメージサイズの削減に貢献

FROM ruby:2.6.3-alpine

ENV LANG=ja_JP.UTF-8
ENV TZ=Asia/Tokyo
ENV ROOT=/myapp \
    GEM_HOME=/bundle \
    BUNDLE_PATH=$GEM_HOME
ENV BUNDLE_BIN=$BUNDLE_PATH/bin
ENV PATH /app/bin:$BUNDLE_BIN:$PATH


WORKDIR $ROOT

RUN apk update && \
    apk upgrade && \
    apk add --no-cache \
        gcc \
        g++ \
        libc-dev \
        libxml2-dev \
        linux-headers \
        make \
        nodejs \
        postgresql \
        postgresql-dev \
        tzdata \
        yarn && \
    apk add --virtual build-packs --no-cache \
        build-base \
        curl-dev

COPY Gemfile $ROOT
COPY Gemfile.lock $ROOT

RUN bundle install -j4
# 不要ファイル削除
RUN rm -rf /usr/local/bundle/cache/* /usr/local/share/.cache/* /var/cache/* /tmp/* && \
apk del build-packs

COPY . $ROOT

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["sh", "/usr/bin/entrypoint.sh"]
EXPOSE 3000

docker-compose.yml

  • macでストレージのアクセスが遅い問題に対応するためvolumeに:cahedオプションを追加
  • webpack-dev-serverを別コンテナで起動させて、hot reloadに対応させています. (ファイル構成に変更があった場合にブラウザのリロード、必要に応じてjavascript周りのコンパイルをしてくれる)
  • dbのhost, user, passwordは後で再利用
version: "3.8"

services:
  db:
    image: postgres:11.0-alpine
    volumes:
      - postgres:/var/lib/postgresql/data:cached
    ports:
      - "5432:5432"
    environment:
      PGDATA: /var/lib/postgresql/data/pgdata
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=ja_JP.UTF-8"
      TZ: Asia/Tokyo
  app:
    build: .
    command: ash -c "rm -f tmp/pids/server.pid && ./bin/rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp:cached
      - rails_cache:/myapp/tmp/cache
      - node_modules:/myapp/node_modules:cached
      - bundle:/bundle:cached
    tmpfs:
      - /tmp
    tty: true
    stdin_open: true
    ports:
      - "3000:3000"
    environment:
      RAILS_ENV: development
      NODE_ENV: development
      DATABASE_HOST: db
      DATABASE_PORT: 5432
      DATABASE_USER: postgres
      DATABASE_PASSWORD: password
      WEBPACKER_DEV_SERVER_HOST: webpacker
    depends_on:
      - db
      - webpacker

  webpacker:
    build: .
    command: ./bin/webpack-dev-server
    volumes:
      - .:/myapp:cached
      - node_modules:/myapp/node_modules:cached
    environment:
      RAILS_ENV: development
      NODE_ENV: development
      WEBPACKER_DEV_SERVER_HOST: 0.0.0.0
    tty: false
    stdin_open: false
    ports:
      - "3035:3035"

volumes:
  rails_cache:
  node_modules:
  postgres:
  bundle:

Gemfile

source 'https://rubygems.org'
gem 'rails',      '6.0.3'

Gemfile.lock

空のファイルで良いのでtouchコマンドのみ

touch Gemfile.lock

entrypoint.sh

#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

手順

Rails 6.0.3をインストールします

docker-compose run app rails new . --force --no-deps --database=postgresql --skip-bundle

Gemfile

Railsチュートリアルに準じて以下のように変更
(Development, test環境でもPostgreSQLを使用するように変更してあります。)

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

gem 'rails',      '6.0.3'
gem 'puma',       '4.3.4'
gem 'pg',         '1.1.4'
gem 'sass-rails', '5.1.0'
gem 'webpacker',  '4.0.7'
gem 'turbolinks', '5.2.0'
gem 'jbuilder',   '2.9.1'
gem 'bootsnap',   '1.4.5', require: false

group :development, :test do
  gem 'byebug',  '11.0.1', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  gem 'web-console',           '4.0.1'
  gem 'listen',                '3.1.5'
  gem 'spring',                '2.1.0'
  gem 'spring-watcher-listen', '2.0.1'
end

group :test do
  gem 'capybara',                 '3.28.0'
  gem 'selenium-webdriver',       '3.142.4'
  gem 'webdrivers',               '4.1.2'
  gem 'rails-controller-testing', '1.0.4'
  gem 'minitest',                 '5.11.3'
  gem 'minitest-reporters',       '1.3.8'
  gem 'guard',                    '2.16.2'
  gem 'guard-minitest',           '2.4.6'
end

group :production do
end

# Windows ではタイムゾーン情報用の tzinfo-data gem を含める必要があります
#gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

Gemfile.lockをアップデート(必要ないかもしれません)

docker-compose run app bundle update

webpackerのインストール

Rails 6ではwebpackerが必要ですが、
このままではインストールされていないためインストールします

docker-compose run app rails webpacker:install

データベースの設定

config/database.yml
host, username, passwordをdocker-compose.ymlと一致させる

default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: password
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

#省略...

docker-compose build

DockerfileやGemfileを変更する度に'build'が必要です
bundle installも実施されるため少し時間がかかります

docker-compose build

いよいよコンテナを起動

docker-compose up

データベース作成

このままだとDBがないよと言われるので、development環境のDBを作成

docker-compose run app rake db:create

動作確認

docker psで起動しているコンテナ確認
DB, Rails, webpack-dev-serverの3つのコンテナが起動しています。

$ docker ps
CONTAINER ID        IMAGE                            COMMAND                  ...              PORTS                              NAMES
1fb4f53d5652        sample_app_on_docker_app         "sh /usr/bin/entrypo…"   ...    0.0.0.0:3000->3000/tcp             sample_app_on_docker_app_1
ccd40c018d53        sample_app_on_docker_webpacker   "sh /usr/bin/entrypo…"   ...    3000/tcp, 0.0.0.0:3035->3035/tcp   sample_app_on_docker_webpacker_1
74392532098a        postgres:11.0-alpine             "docker-entrypoint.s…"   ...    0.0.0.0:5432->5432/tcp             sample_app_on_docker_db_1

ブラウザでlocalhost:3000にアクセスすると

お疲れさまでした"Yay! You’re on Rails!"

Trouble shoot

check_yarn_integrity関連

コンテナをdocker-compose upで起動したときに出るエラー

app_1        | ========================================
app_1        |   Your Yarn packages are out of date!
app_1        |   Please run `yarn install --check-files` to update.
app_1        | ========================================
app_1        | 
app_1        | 
app_1        | To disable this check, please change `check_yarn_integrity`
app_1        | to `false` in your webpacker config file (config/webpacker.yml).
app_1        | 
app_1        | 
app_1        | yarn check v1.16.0
app_1        | info Visit https://yarnpkg.com/en/docs/cli/check for documentation about this command.
app_1        | 
app_1        | 
app_1        | Exiting
sample_app_on_docker_app_1 exited with code 1

config/webpacker.yml
以下のように変更します

#...省略

development:
  <<: *default
  compile: true 

  # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules
  check_yarn_integrity: false # true -> falseに変更

#省略...

"webpack-dev-server" not found

同じくコンテナをdocker-compose upで起動したときに出るエラー

webpacker_1  | yarn run v1.16.0
webpacker_1  | error Command "webpack-dev-server" not found.
webpacker_1  | info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
sample_app_on_docker_webpacker_1 exited with code 1

package.jsonにwebpack-dev-serverが記述されていないはずなので
webpack-dev-serverをインストール

docker-compose run app yarn add webpack-dev-server

おまけ

イメージサイズ 477MB
先人の知恵を多々お借りして軽量化したつもりです。
Dockerを学び始めた頃に作ったのイメージは1.5GBほどありました...

$docker images
REPOSITORY                       TAG                 IMAGE ID            CREATED             SIZE
sample_app_on_docker_app         latest              84aed607a3d2        31 minutes ago      477MB
sample_app_on_docker_webpacker   latest              84aed607a3d2        31 minutes ago      477MB
naokit-dev
Interest: クラウドインフラ / DevOps / AWS / Docker / Ruby on Rails | 2020.05 - 2020.10 30代未経験から5ヶ月間独学にて学び、2020.11からWeb開発エンジニアへ 学習内容を残しています(40投稿, 53LGTM) | Twitterお気軽にフォローください ヒト型のエンジニアらしき人と繋がりたい
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away