環境
- ruby 2.4.1
- Rails 5.1.0(+Puma)
- MySQL 5.7
- Wercker CI
- RSpec + FactoryGirl + Faker
- Rubocop
- Brakeman
Dockerfile
FROM ruby:2.4.1
ENV APP_ROOT /usr/src/app
ENV ENTRYKIT_VERSION 0.4.0
WORKDIR $APP_ROOT
EXPOSE 3000
## SSLのレポジトリをインストールできるようにします
RUN apt-get update && apt-get install -y apt-transport-https
## yarnのレポジトリをインストールします
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
## Nodejsのレポジトリをインストールします
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
# 依存ライブラリをインストールします
RUN apt-get update && apt-get install -y \
nodejs \
mysql-client \
postgresql-client \
sqlite3 \
yarn \
--no-install-recommends && rm -rf /var/lib/apt/lists/*
# EntryKitのインストール
RUN apt-get install openssl \
&& rm -rf /var/cache/apk/* \
&& 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
# Rubyのライブラリをインストール
COPY Gemfile $APP_ROOT
COPY Gemfile.lock $APP_ROOT
RUN bundle install --jobs=4
# レポジトリの内容をコピーしておきます
COPY . $APP_ROOT
# サーバー起動前の処理を定義します
ENTRYPOINT [ \
# 起動前準備スクリプトです。実行権限をつけます。
"prehook", "chmod +x boot.sh", "--", \
# 起動前準備スクリプトを実行します。
"prehook", "bash ./boot.sh", "--"]
解説
アプリのルートディレクトリは/usr/src/appにしていますがこれは特に理由はありません。好みでOKです。yarnのレポジトリがSSLになっているのですが、使っているイメージruby-2.4.1では下記のエラーが出てインストールできませんでした。
E: The method driver /usr/lib/apt/methods/https could not be found.apt-transport-httpsを入れて解決してあります。
## SSLのレポジトリをインストールできるようにします
RUN apt-get update && apt-get install -y apt-transport-https
boot.sh
# Rubyのバージョンを表示します。
ruby -v
# Rubyのライブラリをインストールします。
bundle install -j4
# フロントのライブラリをインストールします。
yarn install --no-optional
# 特定のサーバー・ポートが起動するまで待つスクリプトです。実行権限をつけます。
chmod +x wait-for-it.sh
# MySQL起動を待ちます
./wait-for-it.sh mysql:3306
# DBを更新します。
rake db:create
rake db:migrate
# railsサーバーが起動済だったら殺します
kill -s 9 `pgrep -f 'rails s' `
# pidファイルを消します
rm -f app/tmp/pids/server.pid
boot.shでは以下を行っています。- 依存ライブラリの解決
- MySQLの起動待ち
- DBの更新
- rails sの二重起動防止(killspidファイルも消し、)
MySQLの起動待ちにはwait-for-itを使っています。(rootに配置)
docker-compose.yml
version: '3'
services:
# Railsサーバー
app:
build: . # Dockerfileを元にビルドします
environment:
RAILS_ENV: development
DATABASE_URL: mysql2://root:pass@mysql:3306
PORT: 3000
ports:
- 3000:3000
volumes:
- .:/usr/src/app
- bundle:/usr/local/bundle
depends_on:
- mysql
command: ["rails", "s", "-b", "0.0.0.0"]
# MySQL
mysql:
image: mysql:5.7.10
environment:
MYSQL_ROOT_PASSWORD: 'pass'
ports:
- 7207:3306
volumes:
- mysql-data:/var/lib/mysql
# グローバルにvolumesを書くとホストボリュームになり、ファイルを永続化できます。
volumes:
mysql-data:
driver: local
bundle:
driver: local
docker-composeのバージョン3からホストvolume(グローバルにvolumesを書く)を使ってファイルを永続化しています。これによりbundle installにやり直しが発生しません。MySQLのデータも永続化している為、開発環境のデータが毎回クリアされることもありません。
また、rails5.1からPORT:3000と指定しないとデフォルトの9292ポートでpumaが起動してしまいます。(バグかは追っていません)
config/application.rb
require_relative 'boot'
require 'rails/all'
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module App
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 5.1
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
config.generators do |g|
g.stylesheets false
g.javascripts false
g.helper false
g.test_framework :rspec, view_specs: false, helper_specs: false, fixture: true
g.template_engine = :slim
end
end
end
rails g(enerate) のコマンドの設定を書いています。
- スタイルシート・JS・ヘルパーの生成を無効に(必要なファイルだけ後で生成します)
- テストフレームワークはrspecに
- テンプレートエンジンはslimに
Gemfile
source 'https://rubygems.org'
git_source(:github) do |repo_name|
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
"https://github.com/#{repo_name}.git"
end
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.1.0'
# Use mysql2 as the database for Active Record
gem 'mysql2'
# Use Puma as the app server
gem 'puma', '~> 3.7'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# See https://github.com/rails/execjs#readme for more supported runtimes
gem 'therubyracer', platforms: :ruby
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.2'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
gem 'redis', '~> 3.0'
# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'
# テンプレートエンジンにslimを使います
gem 'slim-rails'
# Use Capistrano for deployment
gem 'capistrano-rails', group: :development
group :development, :test do
# セキュリティチェックのBrakemanを導入
gem 'brakeman', :require => false
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
# Fixtureの代替となるFactoryGirlを導入
gem 'factory_girl_rails'
# テストデータ生成のFakerを導入
gem 'faker'
# Adds Support for RSpec unit testing
gem 'rspec-rails', '~> 3.5'
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '~> 2.13.0'
gem 'selenium-webdriver'
# CSチェック
gem 'rubocop', require: false
end
group :development do
# HTML/ERBからslimに変換します
gem 'html2slim'
gem 'listen', '>= 3.0.5', '< 3.2'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
# Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
gem 'web-console', '>= 3.3.0'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
Gemfileは日本語注釈がついたものを追加したのと、redis, bcryptあたりは後々使いそうだったのでコメントを外しています。
開発運用
docker-compose up -d(初回のみ)docker-compose logs(うまく動かない時のログを見る)
docker-compose restart(gem等がうまくrailsサーバーに伝わらない時実行)
docker-compose down(コンテナを落とす)
docker-compose rm(イメージを消す)
docker-compose exec app bash (擬似的にシェルログインできます。アプリサーバーでコマンド実行 ※これで普通にrailsコマンドが実行できるようになります)
wercker.yml
# 下記を参考に作成しています
# http://qiita.com/masashi-sutou/items/d0fcec3a14c1c89ae702
# This references the default Ruby container from
# the Docker Hub.
# https://registry.hub.docker.com/_/ruby/
# If you want to use a specific version you would use a tag:
# ruby:2.2.2
box: ruby:2.4.1
# You can also use services such as databases. Read more on our dev center:
# http://devcenter.wercker.com/docs/services/index.html
# services:
# - postgres
# http://devcenter.wercker.com/docs/services/postgresql.html
# - mongo
# http://devcenter.wercker.com/docs/services/mongodb.html
services:
- id: mysql
env:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_USER: test_user
MYSQL_PASSWORD: test_password
MYSQL_DATABASE: test_database
# This is the build pipeline. Pipelines are the core of wercker
# Read more about pipelines on our dev center
# http://devcenter.wercker.com/docs/pipelines/index.html
build:
# Steps make up the actions in your pipeline
# Read more about steps on our dev center:
# http://devcenter.wercker.com/docs/steps/index.html
steps:
- install-packages:
name: Install mysql client
packages: mysql-client
- rails-database-yml:
service: mysql-docker
- bundle-install:
jobs: 4
- script:
name: Run RSpec
code: bundle exec rspec
- script:
name: Run Brakeman
code: bundle exec brakeman -qz
mysql clientをインストールする前にbundle installすると、bundle install時にリンクに失敗しているのか、libmysqlclientが見つからないエラーが出ます。
bundle installの結果は永続化されている為、2回目以降のビルドが高速です。
開発が進んだ後で、アプリのビルドイメージを作ってレポジトリに上げたものを使うようにwerckerの設定を修正する予定です。
参考記事・サイト
- Dockerで起動したMySQLのデータを永続化する - ログってなんぼ http://okisanjp.hatenablog.jp/entry/docker_data_volume_container
- 開発しやすいRails on Docker環境の作り方 - Qiita http://qiita.com/joker1007/items/9f54e763ae640f757cfb
- Debian に Docker をインストールしたときのメモ - Qiita http://qiita.com/deep_tkkn/items/38c90cc7ae8ae749a6ae
- Entrykit のすすめ - Qiita http://qiita.com/spesnova/items/bae6406bf69d2dc6f88b
- アプリのサーバーサイドをRailsで構築する - Qiita http://qiita.com/masashi-sutou/items/d0fcec3a14c1c89ae702
- rspecを実行した時にcannot load such file -- spec_helper (LoadError)と言われる解決方法 - Qiita http://qiita.com/pugiemonn/items/55dd0a07c262c2010e2c