(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] (https://qiita.com/naokit-dev/items/7036f05c0f236be8806a)
第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
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