概要
DockerでRails5のAPIモードの開発用環境構築です。
Rails5の中身などについては触れません。
今回作る環境
DBにMySQLを使い、フロントサーバにNginxとUnicornを使います。
必要な環境
macOSXを対象としています。(Windowsでも動くと思いますが、未確認です。)
下記の環境を想定しています。
- docker 1.12.0
- docker-compose 1.8.0
- Rails5
- ruby 2.3
フォルダ構成
フォルダ構成は説明を簡単にするため、Docker関連をRailsアプリのルート直下に置くことにします。
Railsアプリのルート
|- app/
|- config/
|- Gemfile
~
|- docker/
|- nginx/
|- Dockerfile
|- docker-compose.yml
Railsの設定
DB周りの設定
...
production:
adapter: mysql2
encoding: utf8
pool: 5
host: <%= ENV['DB_HOST'] %>
database: <%= ENV['DB_NAME'] %>
username: <%= ENV['DB_USER'] %>
password: <%= ENV['DB_PASS'] %>
次に、Dockerfileを次のようにします。
FROM ruby:2.3.1
RUN cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
RUN apt-get update && \
apt-get install -y libssl-dev && \
rm -rf /var/lib/apt/lists/*
RUN gem install bundler
RUN mkdir -p /app
WORKDIR /app
COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
RUN bundle install --without development test --path vendor/bundle
COPY . /app
EXPOSE 8080
ENTRYPOINT bin/start_server.sh
最後にスクリプトの設定
#!/bin/bash -x
bundle exec rails db:create RAILS_ENV=production
bundle exec rails db:migrate RAILS_ENV=production
bundle exec unicorn -E production -c config/unicorn.rb
$ chmod 755 bin/start_server.sh
と忘れずに行ってください。
2016年8月7日追記
unicornの設定を忘れていました。
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 15
preload_app true
before_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
Process.kill 'QUIT', Process.pid
end
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
end
after_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
end
defined?(ActiveRecord::Base) and
ActiveRecord::Base.establish_connection
end
Nginx
Dockerfileは次のようにします。
FROM nginx
COPY default.conf /etc/nginx/conf.d/default.conf
次にconfファイルを次のようにします。
server {
listen 80;
server_name localhost;
location / {
if (-f $request_filename) { break; }
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://ruby:8080;
}
}
docker-compose.yml
version: '2'
services:
mysql:
image: mysql:5.6
environment:
- MYSQL_ROOT_PASSWORD=password
ports:
- '3306:3306'
nginx:
build: ./docker/nginx
ports:
- '80:80'
links:
- ruby
ruby:
build: .
ports:
- '8080:8080'
links:
- mysql
environment:
## SECRET_KEY_BASEはconfig/secrets.ymlにあります
- SECRET_KEY_BASE=[適当に入力してください]
- DB_HOST=mysql
- DB_USER=root
- DB_PASS=password
- DB_NAME=sample
ここでの注意点ですが、environmentで "
これを使うのは避けましょう。
DB_PASS="pass"
DB_PASS=pass
この2つは別物として扱われてしまいます。
実行
$ docker-machine create -d virtualbox sample
$ docker-machine ls
マシンが作成されたこととACTIVE状態を確認してください
$ eval $(docker-machine env sample)
$ docker-machine ls
ACTIVEになったことを確認してください
$ docker-compose up -d
コンテナを立ち上げます。長いのでひと休憩をとりましょう。
$ docker-compose ps
ruby以外がちゃんと立っていることを確認してください。
$ docker-compose up -d --build
少し長いのでゆっくり待ちましょう
$ docker-compose ps
ちゃんと起動していることを確認してください
もしエラーがあったら docker-compose logs で確認してください
$ docker-machine ip sample
ipアドレスがでます。
メッセージを返すGETのエンドポイントを立てて、ブラウザアクセスで確認してみましょう。
docker-compose up -d
を2回行っている理由ですが、
コンテナの立ち上げに成功するかの確認とmysqlコンテナの立ち上がり前にdbのcreateコマンドが走り、rubyコンテナがこけることがあるからです。
また、今回はdocker-composeでイメージのビルドをしていますが、予めイメージをビルドしておくのが良いと思われます。この場合は docker-compose up -d --build
の --build
を省きます。
最後に
今回の設定は開発用に使うことを推奨します。本番での運営ではお勧めしません。
本番で運営するならmysqlコンテナを削除してRDSなどを使ったり、Fluentdを噛ませてログを別サーバに集約したりすることをお勧めします。