ローカルの Rails の開発環境を直接OSに構築してしまうと、
仕事で別のバージョンの DB が必要になったケースなどで非常に苦労するので
何らかの仮想マシン上に開発環境を構築するほうが楽だと思う。
Vagrant と何かしらのプロビジョニングツールを使う方法がベターだが、
Docker Compose を試しに使ってみたら便利だった。
Docker Compose なに?
Docker における複数コンテナの管理を docker-compose.yml という1ファイルでできるようにするツールです。
詳しくは https://docs.docker.com/compose
Vagrant と比べたメリット
- 設定ファイルが短い。
例えば Vagrant + ansible の場合、Ruby とか PostgreSQL とかのインストール方法を自分で書く必要がありますが、
docker-compose ならコンテナを取得するだけでいいのですごく楽です。
デメリット
- 資料すくない
-
Mac だとやっぱり不安定な感じ。Linux使おう。最近はmac上のdocker-machineでも元気に動きます
Rails の開発環境
https://docs.docker.com/compose/rails/ に Rails の開発環境の作り方があるので、これをベースにします。
次のことをやります。
- Node.js と phantom.js をいれる
- Rails console 上で日本語入力できるように
ENV LANG C.UTF-8
を指定 - bundle install した gem をキャッシュする
Dockerfile
FROM ruby:2.2.3
ENV LANG C.UTF-8
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs npm nodejs-legacy
RUN npm install -g phantomjs-prebuilt
RUN gem install bundler
ENV APP_HOME /myapp
RUN mkdir $APP_HOME
WORKDIR $APP_HOME
ADD Gemfile* $APP_HOME/
ENV BUNDLE_GEMFILE=$APP_HOME/Gemfile \
BUNDLE_JOBS=2 \
BUNDLE_PATH=/bundle
ADD . $APP_HOME
docker-compose.yml
db:
image: postgres
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/myapp
ports:
- "3000:3000"
links:
- db
volumes_from:
- bundle
environment:
- DB_USERNAME=postgres
- DB_PASSWORD=
- DB_HOST=db
bundle:
image: myapp_web
volumes:
- /bundle
使っている感じ、環境変数は dotenv 等で設定するより docker-compose.yml で設定するほうが無難そうです。
bundle install で取得した gem をキャッシュする
https://docs.docker.com/compose/rails/ の場合、 bundle install
や bundle update
のたびに全 gem を取得するので時間がかかります。
上記の docker-compose.yml
にあるように bundle path を別の volume に切り出すことでキャッシュできます。
docker-compose run web bundle install
docker-compose run web bundle update
Rails new
上記の Dockerfile
と docker-compose.yml
を使って Rails プロジェクトを作成します。
(https://docs.docker.com/compose/rails/ と同じです)
まず、次のファイルを同じディレクトリに置きます。
- Gemfile
- Dockerfile
- docker-compose.yml
Gemfile
の内容:
source 'https://rubygems.org'
ruby '2.2.3'
gem 'rails'
次のコマンドを実行します。
docker-compose build
docker-compose run web bundle install
docker-compose run web bundle exec rails new . --force --database=postgresql --skip-bundle
これでホストOSに ruby さえ入れずに rails new
できました。
生成されたファイルが root ユーザーの所有になってしまうので chown
で自分の所有に変えます。
(これ改善方法あれば教えてください。)
database.yml
で host: db
を指定します:
default: &default
adapter: postgresql
encoding: unicode
pool: 5
username: <%= ENV['DB_USERNAME'] %>
password: <%= ENV['DB_PASSWORD'] %>
host: <%= ENV['DB_HOST'] %>
development:
<<: *default
database: myapp_development
test:
<<: *default
database: myapp_test
これで DB も使えるようになるので次のコマンドを実行します。
docker-compose run web bundle exec rake db:setup
Rails server を起動:
docker-compose up
docker-compose run web bundle exec rails s
でも起動できますが、ホストOSのポートとDocker中のポートを結びつける必要があるので
docker-compose up
を使います。
テスト実行:
docker-compose run web bundle exec rake spec
docker-compose run web bundle exec rake test
[小ネタ] docker-compose up 時の rails server のログ
Linuxで docker-compose up
したとき以前起動した時の rails server
のログが無駄に表示されるので邪魔なときは
次のコマンドで消してからサーバーを起動します。
(この現象はなぜか Mac では発生しません)
docker-compose rm web
docker-compose up
雑感
こんな感じでちょっとの設定ファイルを用意すれば rails を動かす環境を作れます。
ホストOSに余計なものが入らないのは快適ですね。
プロジェクトで他の人が docker-compose を使いたくない場合も database.yml だけリポジトリ内で工夫すれば使えます。
若干困っていること
-
rails generate
等のコマンドを docker-compose 経由で実行した時に生成されるファイルが root 権限になるのでユーザー権限で作りたい(Linuxでのみ発生) -
rails server
の古いログをdocker-compose up
時に表示しないようにしたい- 以前立ち上げた docker が残っているので、
docker-compose stop
すると消せます
- 以前立ち上げた docker が残っているので、
-
コメント欄で解決方法を教えて頂きました。ありがとうございます!!rails console
で日本語が使えない -
rails server
起動中にbyebug
が使えない (byebug -R
をうまく使えればいけそう)-
docker-compose up
ではなくdocker-compose run --service-ports web bundle exec rails s -b 0.0.0.0
でサーバーを起動すればデバッガが使えます。
-
解決方法ご存じの方がいれば教えてください