追記(2018/07/07)
node
バイナリと yarn
バイナリのインストールを、node
の docker image からコピーする方式に改善しました。
参考URL: https://qiita.com/izumin5210/items/cf14a1ea58fb82d36bb2
はじめに
docker-composeを使い、railsを簡単に開発できるテンプレートを作成しました。
webpackerの利用にも対応しています。
特徴は以下の通りです。
-
bundle install
をdockerイメージビルドの時でなく、ENTRYPOINTで行います。- インストールされたgemがDockerVolumeにキャッシュされるので、
Gemfile
を更新してもイメージの再ビルドをする必要がありません。
- インストールされたgemがDockerVolumeにキャッシュされるので、
-
webpacker
にも対応。webpack-dev-server
が自動で起動されます。
webフロントエンドは違うリポジトリで作るという考え方もありますが、このテンプレートを使うと、heroku
にそのままアップロードすることで、フロントエンド、バックエンド双方が一つのサーバーで供給されるようになり、運用が楽になります。
前回との違い
1年前に高速に開発できる Docker + Rails開発環境のテンプレートを作ったで、Docker + railsのテンプレートを紹介しましたが、以下の点が変わっています。
- webpackerに対応
- webpackerを動かせるように、Node8の環境とyarnがインストールされています。
-
webpack-dev-server
が自動で起動されます。
-
spring
コンテナの廃止-
spring
コンテナがあることで高速に各種コマンドを実行できていましたが、rails
コンテナで十分だということに気づいたため、廃止しました。 -
spring
コンテナとrails
コンテナを同時に起動すると、bundle install
が同時に実行され同じ、bundle pathを共有してみているためエラーが起こることがありました。
-
公開
ソースコードは、kawasin73/rails_docker_templateで公開しています。
ブランチごとに環境を分けました。
base/ruby-x.x.x-rails-x.x.x
は、テンプレートの状態のブランチです。各自の環境でアプリケーションのビルドを行う必要があります。
base
ブランチには、全てまとめて、Initial Commit
の1コミットしか含まれないようにしました。
git clone https://github.com/kawasin73/rails_docker_template.git .
git checkout origin/base/ruby-2.5.1-rails-5.2.0
git branch -d master && git checkout -b master
script/init && script/bootstrap
docker-compose exec rails bash
# access to http://localhost:3000
ruby-x.x.x-rails-x.x.x
は、ビルド済みのテンプレートです。credentials.yml.enc
を削除した状態でリポジトリにおいてあるので、credentials情報を初期化してから使う必要があります。
git clone https://github.com/kawasin73/rails_docker_template.git .
git checkout base/ruby-2.5.1-rails-5.2.0
git branch -d master && git checkout -b master
# initialize credentials.yml.enc
docker-compose run --rm rails bin/rails credentials:edit
script/bootstrap
docker-compose exec rails bash
# access to http://localhost:3000
現在(2018/04/14)公開しているブランチは以下の通りです。
- master
- 標準テンプレートの開発ブランチ
- webpacker
- webpacker環境の開発ブランチ
-
base/ruby-2.5.1-rails-5.2.0
- Ruby 2.5.1, Rails 5.2.0のテンプレートです。webpacker環境は含まれていません。
-
base/ruby-2.5.1-rails-5.2.0-webpack
- Ruby 2.5.1, Rails 5.2.0のwebpackerを使う時のテンプレートです。
-
ruby-2.5.1-rails-5.2.0
- Ruby 2.5.1, Rails 5.2.0のビルド済みアプリケーションです。
-
ruby-2.5.1-rails-5.2.0-webpack
- Ruby 2.5.1, Rails 5.2.0のwebpacker用のビルド済みアプリケーションです。
僕が必要になったら随時追加されていくと思います。
テンプレートの中身
base/ruby-2.5.1-rails-5.2.0-webpackを解説していきます。
前回の高速に開発できる Docker + Rails開発環境のテンプレートを作ったと重複している部分の解説は元記事からコピーします。
Dockerfile.dev
docker-compose.yml
Gemfile
.env.dev.sample
template/database.yml
.gitignore
script/init
script/bootstrap
Dockerfile.dev
FROM node:10.6.0 as node
FROM ruby:2.5.1
ENV LANG C.UTF-8
RUN apt-get update -qq && \
apt-get install -y --no-install-recommends \
build-essential \
libpq-dev \
libfontconfig1 && \
rm -rf /var/lib/apt/lists/*
ENV ENTRYKIT_VERSION 0.4.0
RUN wget https://github.com/progrium/entrykit/releases/download/v${ENTRYKIT_VERSION}/entrykit_${ENTRYKIT_VERSION}_Linux_x86_64.tgz \
&& tar -xvzf entrykit_${ENTRYKIT_VERSION}_Linux_x86_64.tgz \
&& rm entrykit_${ENTRYKIT_VERSION}_Linux_x86_64.tgz \
&& mv entrykit /bin/entrykit \
&& chmod +x /bin/entrykit \
&& entrykit --symlink
ENV YARN_VERSION 1.7.0
COPY --from=node /opt/yarn-v$YARN_VERSION /opt/yarn
COPY --from=node /usr/local/bin/node /usr/local/bin/
RUN ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \
&& ln -s /opt/yarn/bin/yarnpkg /usr/local/bin/yarnpkg
RUN mkdir /app
WORKDIR /app
RUN bundle config build.nokogiri --use-system-libraries
ENTRYPOINT [ \
"prehook", "ruby -v", "--", \
"prehook", "bundle install -j3 --quiet", "--"]
オフィシャルのnode
イメージからnode
バイナリとyarn
バイナリをコピーしています。
ファイル名はあえて「Dockerfile.dev」にしています。開発環境と本番環境ではDockerfile
の中身は変わってくると思うので、Dockerfile
は別途作って本番環境用に使うことができます。
ENV LANG C.UTF-8
によって rails console
の中で日本語の入力をできるようにしています。
最大の特徴は、ENTRYKIT
だと思います。開発しやすいRails on Docker環境の作り方を参考にしました。
ENTRYPOINT
の中で bundle install
を行うことでインストールした gem をDocker Volumeの中にキャッシュすることができます。
Dockerfile
の中でbundle install
をしないので、新しくgemを追加した時に、Dockerイメージを再度ビルドする必要がなく、高速に開発を進めることができます。
開発環境では、ローカルのrailsディレクトリを、Dockerコンテナにマウントして開発します。
そのため、Dockerfile.dev
では、COPY . /app
をしません。RUN mkdir /app
で/app
ディレクトリを作成するだけにとどめます。
docker-compose.yml
version: '2'
services:
rails: &app_base
build:
context: .
dockerfile: "Dockerfile.dev"
command: ["bundle", "exec", "rails", "s", "-p", "3000", "-b", "0.0.0.0"]
env_file:
- "./.env.dev"
volumes:
- ".:/app"
volumes_from:
- data
ports:
- "3000:3000"
depends_on:
- db
tty: true
stdin_open: true
webpack:
<<: *app_base
command: "bin/webpack-dev-server"
ports:
- "3035:3035"
depends_on:
- rails
tty: false
stdin_open: false
db:
image: "postgres:10.3"
environment:
- "POSTGRES_USER=postgres"
- "POSTGRES_PASSWORD=password"
volumes_from:
- data
ports:
- "5432:5432"
data:
image: "busybox"
volumes:
- "db:/var/lib/postgresql/data"
- "bundle:/usr/local/bundle"
volumes:
db:
driver: local
bundle:
driver: local
webpack
コンテナが追加されました。
コマンドは、
docker-compose up -d
docker-compose exec rails bin/rails db:migrate
のように実行できます。
Gemfile
# frozen_string_literal: true
# A sample Gemfile
source 'https://rubygems.org'
ruby '2.5.1'
gem 'rails', '5.2.0'
最初の状態では、gem 'rails', '5.2.0'
のみを書きます。後述のscript/init
で、rails new
することでGemfile
の中身を増やしてくれます。
また、Gemfile.lock
はこの時点では必要ありません。
.env.dev.sample
DATABASE_HOST=db
DATABASE_PORT=5432
DATABASE_USER=postgres
DATABASE_PASSWORD=password
EDITOR=vim
データベースの情報は環境変数で railsアプリケーションに渡します。
cp .env.dev.sample .env.dev
を実行して利用してください。
EDITOR=vim
は、Rails5.2から導入されたrails credentials:edit
のエディタを指定します。
template/database.yml
default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: <%= ENV.fetch('DATABASE_USER') { 'root' } %>
password: <%= ENV.fetch('DATABASE_PASSWORD') { 'password' } %>
host: <%= ENV.fetch('DATABASE_HOST') { 'localhost' } %>
port: <%= ENV.fetch('DATABASE_PORT') { 5432 } %>
development:
<<: *default
database: app_development
test:
<<: *default
database: app_test
production:
<<: *default
database: app_production
データベースの情報は環境変数で railsアプリケーションに渡します。
cp -f template/database.yml config/database.yml
で、自動生成されるdatabase.yml
を上書きします。
.gitignore
/log
/tmp
!/log/.keep
!/tmp/.keep
/public/system
/public/packs
/node_modules
.env
.env.dev
/.bundle
/vendor/bundle
/.idea
.DS_Store
そのままです。
script/init
#!/usr/bin/env bash
cp .env.dev.sample .env.dev
docker-compose build
docker-compose run --rm rails bundle exec rails new . --force --database=postgresql --skip-turbolinks --skip-git --skip-test --webpack=react
cp -f template/database.yml config/database.yml
sed -i ".bak" -e "s/host: localhost/host: webpack/g" config/webpacker.yml
docker-compose run --rm rails bundle exec spring binstub --all
webpack-dev-server
が起動するdockerコンテナのIPは、localhost
ではないです。
sed -i ".bak" -e "s/host: localhost/host: webpack/g" config/webpacker.yml
development.dev_server.host
には、webpack-dev-server
を稼働させてるコンテナのDockerネットワーク内でのホスト名webpack
を設定します。
0.0.0.0
を設定しても、webpacker-dev-server
は稼働しますが、HMRが正しく動かなくなるため、ホスト名を指定します。
一方、Docker for Mac
では、IPアドレスはホストマシンから127.0.0.1
として見えます。そのため、development.dev_server.public
は、デフォルトのlocalhost:3035
のまま変更しません。
script/bootstrap
#!/usr/bin/env bash
cp .env.dev.sample .env.dev
docker-compose run --rm rails rails db:create
docker-compose run --rm rails rails db:migrate
docker-compose run --rm rails bin/yarn install
docker-compose up -d
script/init
を実行して作成済みのプロジェクトを、git clone
してきた後などに実行します。データベースの作成ができます。
binding.pry
を使う
docker-compose.yml
で
tty: true
stdin_open: true
を設定しています。これによって、pumaのサーバーの処理に挿入したbinding.pry
を使えるようになります。
docker ps
コマンドで、railsコンテナのコンテナ名を調べてください。
docker attach xxxx_rails_1 # xxxx_rails_1 は調べたコンテナ名
とすると、binding.pryをDockerの中で使えるようになります。