- 投稿日:2019-01-26T20:48:01+09:00
Bootstrap4 hoverした時のリンクの背景色を変えたい
- 投稿日:2019-01-26T20:42:07+09:00
cloud9 と GitHub を使ってRailsアプリを開発する際の下準備
内容
cloud9 と GitHub を使ってRailsアプリを開発する際の下準備
なぜcloud9上でRailsアプリを開発するのか?
A. 従来はローカル環境(Mac)とGitHubを利用してアプリ開発をしていた。
しかし、ある時からnokogiri
がインストールできないためローカルでの開発が困難に。「Rubyの開発をするにはcloud9でやったほうがいい」とのアドバイスをいただいたので、cloud9とGitHubで開発することにした。
具体的な下準備
cloud9 に git をインストール
command-on-cloud9gem intall gitバージョンを指定してRailsのインストール
command-on-cloud9gem install rails -v 5.1.6cloud9からGitHubにUP
command-on-cloud9git init git add . git commit -m "Write your comment here." git remote add origin [your GitHub repository] git push -u origin master
- 投稿日:2019-01-26T18:35:51+09:00
FactoryBot で汎用的な skip Validation, save(validate: false)
パッと見どこにも書いてなかったので覚書
Validation を無視して FactoryBot を使った Model を作成するとき、よくある方法
spec/factories/users.rbFactoryGirl.define do factory :user do name 'HAZI' age 31 to_create { |instance| instance.save(validate: false) } end endこの方法だと、該当のモデル(この場合 User)を作成するとき、全てにおいて Validation がスキップされるのでよろしくない。
なので、下記のように
trait
を使ってcreate(:user, :skip_validate)
と指定した時のみ validation を無効にする。spec/factories/users.rbFactoryGirl.define do factory :user do name 'HAZI' age 31 trait :skip_validate do to_create { |instance| instance.save(validate: false) } end end endが、そもそも
trait
はfactory
ネームスペース外で定義すれば共有できるので、spec/factories/traits.rb
を作成しそこで定義をすることで全てのモデルで利用できるようになる。spec/factories/traits.rbFactoryBot.define do trait :skip_validate do to_create { |instance| instance.save(validate: false) } end end
- 投稿日:2019-01-26T18:24:41+09:00
[RSpec] CapybaraでCSSの●番目の要素を指定したい!(同じ要素が複数あるとき)
例えば
class: "fa-pen"
が3個あるときfind(".fa-pen").click→Rails「何個目の
".fa-pen"
だよ??」こうする
first(".fa-pen").click→1個目を取り出す
2個目以降は??
second(".fa-pen").click↓
Failure/Error: second(".fa-pen").click NoMethodError: undefined method `second' for #<RSpec::ExampleGroups〜〜〜
ダメじゃん。。
2個目以降は、【配列から取り出す】
page.all(".fa-pen")[1].click→配列のindexが1なので、2個目を取り出す
(1個目を取り出す場合は、[0]とする)お世話になりました
参考:Capybara で同名の CSS セレクタを持つ複数の HTML 要素から任意の要素を見つける
https://easyramble.com/find-html-element-with-capybara.html
おわり
- 投稿日:2019-01-26T18:01:44+09:00
[RSpec] (feature) Capybaraでfill_in使って失敗するとき
こんなコードがありました
<%= provide(:title, "Create New List") %> <div class="listsnewPage"> <div class="container"> <%= form_with model: @list, url: lists_path, class: "new_list" do |f| %> <%= f.label :title, "List Title" %> <span>(1〜20 characters)</span> <%= f.text_field :title, autofocus: true, autocomplete: "off", class: "form-control listName" %> <div class="text-center"> <%= f.submit "Create", class: "submitBtn" %> </div> <% end %> </div> </div>こんなテストを書きました(feature spec, js: true)
fill_in "List Title", with: "created_now"→ダメ
fill_in ".form-control", with: "created_now"→ダメ!!!!
fill_in使ってるのにformに入力できない問題発生
いきなりですが
参考:Rspec Capybaraで実際テストを書いて困ったシチュエーションの解消法
https://qiita.com/kon_yu/items/52a0f5f0016564486061fill_in
form(input)にidまたはnameが指定されていないと使えない
class指定の場合は???
こうする
find(".form-control").set("created")通ったーーーーー!!!!!!!
けど
なんでf.labelに"List Title"って設定してるのに通らないんだろ?
わからん。。とりあえず
fill_inでダメなときはfind使ってみるといいことあるかも
(根本的な解決には至っていない可能性)
おわり
- 投稿日:2019-01-26T17:49:03+09:00
[RSpec] (feature) js: trueのテストが通ったり通らなかったり(成功・失敗を繰り返す)
こんなfeature specを書いたのだ
spec/features/lists_operation_spec.rbRSpec.feature "ListsOperation", type: :feature do feature "create and destroy lists", js: true do scenario "create a list" do visit root_path expect(current_path).to eq root_path click_on "Create List" expect(current_path).to eq new_list_path # failed with invalid parameters find(".form-control").set("") expect do find(".submitBtn").click end.not_to change(List, :count) expect(current_path).to eq new_list_path # succeeded with valid params find(".form-control").set("created") expect do find(".submitBtn").click end.to change(List, :count).by(1) expect(current_path).to eq root_path expect(page).to have_selector "h2", text: "created" expect(page).to have_selector "div.lists", count: lists.count + 1 save_screenshot end end end
すると
ListsOperation create and destroy lists Capybara starting Puma... * Version 3.12.0 , codename: Llamas in Pajamas * Min threads: 0, max threads: 4 * Listening on tcp://127.0.0.1:51883 shows lists create a list edit a list delete a list Finished in 3.49 seconds (files took 0.29178 seconds to load) 4 examples, 0 failures
落ちなかったり(これが正常)
Capybara starting Puma... * Version 3.12.0 , codename: Llamas in Pajamas * Min threads: 0, max threads: 4 * Listening on tcp://127.0.0.1:51973 shows lists create a list (FAILED - 1) edit a list delete a list Failures: 1) ListsOperation create and destroy lists create a list Failure/Error: expect do find(".submitBtn").click end.to change(List, :count).by(1) expected `List.count` to have changed by 1, but was changed by 0 # ./spec/features/lists_operation_spec.rb:35:in `block (3 levels) in <main>' # -e:1:in `<main>' Finished in 3.34 seconds (files took 0.30711 seconds to load) 4 examples, 1 failure
落ちたり。。。
調べたゾイ
参考:Rspecのフィーチャーテストが失敗したりしなかったり(StackOverFlow)
https://ja.stackoverflow.com/questions/463/rspec%E3%81%AE%E3%83%95%E3%82%A3%E3%83%BC%E3%83%81%E3%83%A3%E3%83%BC%E3%83%86%E3%82%B9%E3%83%88%E3%81%8C%E5%A4%B1%E6%95%97%E3%81%97%E3%81%9F%E3%82%8A%E3%81%97%E3%81%AA%E3%81%8B%E3%81%A3%E3%81%9F%E3%82%8A
js: trueを付けるとJSの処理が終わる前にRSpec側が先に進んでしまい、
本来通るはずのテストがパスしない、もしくはタイミングによってパスするときと失敗するときがある、
ということは僕も良く体験しています。へ〜〜〜〜〜〜〜〜!!!!!!!!!!
そうなんだ。。
というわけで、該当部の下にsleep 3
をつけて試してみる。spec/features/lists_operation_spec.rbfind(".form-control").set("created") expect do find(".submitBtn").click end.to change(List, :count).by(1) sleep 3 # ←これ expect(current_path).to eq root_path
すると、何回繰り返しても
ListsOperation create and destroy lists Capybara starting Puma... * Version 3.12.0 , codename: Llamas in Pajamas * Min threads: 0, max threads: 4 * Listening on tcp://127.0.0.1:51883 shows lists create a list edit a list delete a list Finished in 3.49 seconds (files took 0.29178 seconds to load) 4 examples, 0 failuresOh my goodness
素晴らしいですね。
ですが、sleep 3だとテストに時間がかかってしまう
ので、sleep 0.5にしました。spec/features/lists_operation_spec.rbfind(".form-control").set("created") expect do find(".submitBtn").click end.to change(List, :count).by(1) sleep 0.5 # ←3から0.5にしたゾイ expect(current_path).to eq root_pathというわけで
無事解決!!
- 投稿日:2019-01-26T15:32:21+09:00
小さく薄くrails newする(ViewやJSが必要ない場合)
HerokuでRubyのスクリプトのような何かを動かす時に、activerecord等は利用したいのでRuby単体ではなくてRailsとしての方が都合がいいのだけどViewやJS関係は特に必要ない。そんな時があります。
そういうわけで、上記のような用途向けのView関連、JS関連のファイルの作成の全てをスキップしたrails new
のオプション構成を調べました。確認環境は
- Rails 5.2.2 (Ruby 2.6.0)
です。
結論
結論は下記です。
rails new . --database=postgresql --skip-yarn --skip-git --skip-action-mailer --skip-active-storage --skip-action-cable --skip-sprockets --skip-javascript --skip-turbolinks --skip-test --api --skip-bundle各オプションの解説
各オプションの概要は下記の通りです。
オプション 効果 --database=DATABASE 使用するdatabaseを指定 --skip-yarn Yarnを利用しない --skip-git .gitignore を作成しない --skip-action-mailer Action Mailer関連のファイルを作成しない --skip-active-storage Active Storage関連のファイルを作成しない --skip-action-cable Action Cable関連のファイルを作成しない --skip-sprockets Sprockets関連のファイルを作成しない --skip-javascript JavaScript関連のファイルを作成しない --skip-turbolinks turbolinks gemを利用しない --skip-test test関連ファイルを作成しない --api APIとして利用するapp向けの小さい構成 --skip-bundle bundle installを実行しない 詳しくは
rails new --help
でどうぞ。
補足しておくと、
- 利用DBはPostgreSQL
- 予め
.gitignore
は用意しているので デフォルトの.gitignore
は作成しない (-skip-git
)- どうせあとでRspecをインストールするので標準のtest関連ファイルは必要ない (
--skip-test
)- どうせあと後でGemfileに必要なgemを追加して
bunde install
するのでbundle install
しない (--skip-bundle
)です。
参考: 上記オプション付与時の差分等
removeされるファイル一覧
参考までに、上記オプション付与時にremoveされるファイルは下記の通りです。
ちゃんとどのファイルが削除されるのか表示されて便利だ……。rails new . --database=postgresql --skip-yarn --skip-git --skip-action-mailer --skip-action-cable --skip-sprockets --skip-javascript --skip-turbolinks --skip-test --api --skip-bundle (中略) remove app/assets remove lib/assets remove tmp/cache/assets remove app/helpers remove test/helpers remove app/views remove public/404.html remove public/422.html remove public/500.html remove public/apple-touch-icon-precomposed.png remove public/apple-touch-icon.png remove public/favicon.ico remove app/assets/javascripts remove config/initializers/assets.rb remove app/views/layouts/mailer.html.erb remove app/views/layouts/mailer.text.erb remove app/mailers remove test/mailers remove app/assets/javascripts/cable.js remove app/channels remove config/initializers/cookies_serializer.rb remove config/initializers/content_security_policy.rb remove config/initializers/new_framework_defaults_5_2.rb remove bin/yarnGemfile差分
また、作成されるGemfileとデフォルトのGemfile(
Gemfile.default
)の差分は下記となります。デフォルトのGemfileと比べると、
sass-rails
,coffee-rails
から始まってweb-console
, またtestのcapybara
,selenium-webdrive
に至るまでViewに関するgem一式が削除されていることがわかりますね。git diff --no-index -U10 Gemfile.default Gemfilediff --git a/Gemfile.default b/Gemfile index e45e610..c5441b8 100644 --- a/Gemfile.default +++ b/Gemfile @@ -1,62 +1,40 @@ source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.6.0' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.2.2' # Use postgresql as the database for Active Record gem 'pg', '>= 0.18', '< 2.0' # Use Puma as the app server gem 'puma', '~> 3.11' -# 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 'mini_racer', 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', '~> 4.0' +# gem 'jbuilder', '~> 2.5' # Use ActiveModel has_secure_password # gem 'bcrypt', '~> 3.1.7' -# Use ActiveStorage variant -# gem 'mini_magick', '~> 4.8' - # Use Capistrano for deployment # gem 'capistrano-rails', group: :development # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.1.0', require: false +# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible +# gem 'rack-cors' + group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] end group :development do - # Access an interactive console on exception pages or by calling 'console' anywhere in the code. - gem 'web-console', '>= 3.3.0' 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' end -group :test do - # Adds support for Capybara system testing and selenium driver - gem 'capybara', '>= 2.15' - gem 'selenium-webdriver' - # Easy installation and use of chromedriver to run system tests with Chrome - gem 'chromedriver-helper' -end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]参考リンク
- 投稿日:2019-01-26T14:27:30+09:00
railsのキャッシュの速度を計測してみた
初めに
cacheについて調べて実際に計測してみた
参考記事
Railsのフラグメントキャッシュについて調べてみた
https://qiita.com/suketa/items/eeae7e2196520323f694環境
userが1000件あってそれを読み込む
rails dev:cacheでcacheを有効にする。
users_controllerに
def index @users = User.all endviewを
index.html.erb<h1>Users#index</h1> <p>Find me in app/views/users/index.html.erb</p> <% @users.each do |user| %> <%= user.first_name %> <%= user.last_name %> <%= user.phone %> <%= user.address %> <% end %>これがキャッシュを使っていない普通の状態
実行してみると
Completed 200 OK in 198ms (Views: 173.6ms | ActiveRecord: 11.2ms) Completed 200 OK in 48ms (Views: 41.7ms | ActiveRecord: 2.4ms) Completed 200 OK in 51ms (Views: 45.0ms | ActiveRecord: 2.6ms)最初は200ms位でそのあとは50ms位です
次にcacheを使ってみる
まずこんな感じのコードを書いてみた
index.html.erb<h1>Users#index</h1> <p>Find me in app/views/users/index.html.erb</p> <% @users.each do |user| %> <% cache user do %> <%= user.first_name %> <%= user.last_name %> <%= user.phone %> <%= user.address %> <% end %> <% end %>結果はこんな感じ
Completed 200 OK in 993ms (Views: 976.4ms | ActiveRecord: 4.3ms) Completed 200 OK in 364ms (Views: 343.8ms | ActiveRecord: 15.7ms) Completed 200 OK in 393ms (Views: 386.7ms | ActiveRecord: 2.7ms)時間はめっちゃ長くなった....
このキャッシュのやり方は調べたら結構出てきたやり方だけど使いどころは考えないといけないのかも…
とくに内容が特に無く数が多くなるものに関してはあんま良くないのかな?わかんないけど…
次にこのコード
users_controllerに
def index @user_cache = User.last @users = User.all endviewは
index.html.erb<% cache(@user_cache) do %> <h1>Users#index</h1> <p>Find me in app/views/users/index.html.erb</p> <% @users.each do |user| %> <%= user.first_name %> <%= user.last_name %> <%= user.phone %> <%= user.address %> <% end %> <% end %>これで結果は
Completed 200 OK in 214ms (Views: 197.8ms | ActiveRecord: 3.5ms) Completed 200 OK in 32ms (Views: 28.2ms | ActiveRecord: 0.2ms) Completed 200 OK in 34ms (Views: 29.5ms | ActiveRecord: 0.3ms)初回は197msと遅いがそのあとは30ms以下と早くなった。
確かに二回目からの読み込みが少し早くなるけど正直cache使わないのとたいして変わらなかったのでまだあんまりcacheの良さがわからない…
多分使い方なんだろうけどとりあえずcache使えば良いってわけではなさそう
おわり
- 投稿日:2019-01-26T12:46:20+09:00
知識0から始めるRails on Docker
はじめに
Railsの勉強を始めようと思ったが、どうせならDockerを使って仮想環境で開発したい。
しかしどちらも実務で使ったことがないためよくわからない(というかRubyすら触ったことがない)。ということで、一から調べてみた。RailsとDockerの欲張りセット。
筆者はMacBookProを使っているため、MacOS向けの記事となります。tl;td
- Rubyにまつわる各用語の確認、ローカル環境でRailsの導入・起動方法の確認
- 手動でDocker上でのRailsの導入・起動方法の確認
dockerfile
にRailsの導入・起動情報を文書化して格納し、docker-compose
から呼び出して起動対象読者
- わたし
- これからRailsを勉強しようという方
- これからDockerを勉強しようという方
ロードマップ(超簡易版)
最終目標:Dockerによる仮想環境上でRails serverを起動し、開発できるようにする
※RailsのデフォルトサーバーはPumaです。この記事ではデフォルトのままなのでPumaを使いますが、便宜上「Rails server」と呼称します。
- Railsをローカル環境で起動する
- ローカル環境にRubyを導入する
- ローカル環境にRailsを導入する
- Railsプロジェクトを作成し、Rails serverを起動
- Docker環境を構築して仮想環境でRails serverを起動する
- ローカル環境にDockerを導入する
- DockerでRubyを使える仮想環境を構築する
- 仮想環境でRails serverを起動する
dockerfile
とdocker-compose
を使ってコマンド一つでRails serverを起動する
dockerfile
を作成するdocker-compose.yml
を作成し、起動するRailsをローカル環境で起動する
これについては各所でがっつり解説されているので、ここでは流れ・用語の説明と参考資料の紹介にとどめます。
なお、この章の目的はRubyにまつわる各用語とRails serverの起動までの流れについて確認することが目的なので、既にバッチリの方は飛ばしてください。
参考資料:Ruby初学者のRuby On Rails 環境構築【Mac】ローカル環境にRubyを導入する
流れ
Homebrewの導入(更新)-> rbenvの導入 -> Rubyの導入ざっくりHomebrew解説
- MacOSにおけるパッケージ管理ツール
- Rubyのためだけのものではない
- 参考資料:homebrewとは何者か。仕組みについて調べてみた
ざっくりrbenv解説
- Rubyのバージョンを管理するためのツール
- Rubyのバージョン管理をrbenvで、rbenvのバージョン管理をHomebrewで行う(Homebrewは自分でやる)
- 参考資料:rbenvとは?(rbenvを利用したRubyのインストール)
ローカル環境にRailsを導入する
流れ
Bundlerの導入 -> BundlerでGemfileの作成 -> Gemfileの編集 -> Gemの取得(Railsの導入)ざっくりGem解説
- RubyGemsが公開しているライブラリ
- 要はRubyの開発で使える便利なツール群のこと
- RailsもGemの一つ
- 参考資料:Ruby on Rails 初心者必見!パッケージ管理ツール『gem』を徹底解説
ざっくりBundler解説
- Gemの管理ツール
Gemfile
から利用するGemの情報を読み取り、ライブラリを自動で構築してくれるすごいヤツ- この記事では
$ bundle init
と$ bundle install
さえ覚えておけばOK- 参考資料:Bundlerの使い方
- 参考資料:bundle install と bundle updateの違いについて
Railsプロジェクトを作成し、Rails serverを起動
流れ
Railsからプロジェクトを作成 -> Rails serverの起動 -> 接続確認Docker環境を構築して仮想環境でRails serverを起動する
ローカル環境にDockerを導入する
Docker公式から最新版を取得しましょう。
アカウントの登録が必要です。なお、Dockerの基礎的な仕組みやコマンドなどについては、以下の参考資料がおすすめです。
参考資料:Dockerでプログラマが最低限知るべきことが、最速でわかるチュートリアル
docker
参考資料:【図解】Dockerの全体像を理解する -前編-ざっくりDocker解説
- 仮想環境の構築・管理を行うツール
- 擬似的に様々な環境を構築することができ、ローカル環境と本番環境との差異を減らすことができる
- 「本番環境で急に動かなくなった問題」や「環境構築面倒すぎる問題」の救世主……らしい
DockerでRubyを使える仮想環境を構築する
参考資料:RailsアプリをDockerで開発するための手順
ここからが本題です。
まずは利用するイメージを決めます。Docker Hubにruby
という便利なイメージが用意されているので、ありがたく使わせていただきましょう。rubyイメージの取得$ docker pull ruby
イメージが取得できたら早速run……する前に、このイメージについて調べましょう。
イメージの情報を出力$ docker inspect ruby
コマンドを実行すると大量の文字が吐き出されます。
目眩がするかもしれませんが、頑張って大事な記述を確認しましょう。注目するのは以下の場所です。"ContainerConfig": { …… "Env": [ "PATH=/usr/local/bundle/bin:/usr/local/bundle/gems/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "RUBY_MAJOR=2.6", "RUBY_VERSION=2.6.0", "RUBY_DOWNLOAD_SHA256=acb00f04374899ba8ee74bbbcb9b35c5c6b1fd229f1876554ee76f0f1710ff5f", "GEM_HOME=/usr/local/bundle", "BUNDLE_PATH=/usr/local/bundle", "BUNDLE_SILENCE_ROOT_WARNING=1", "BUNDLE_APP_CONFIG=/usr/local/bundle" ], ……
RUBY_VERSION=2.6.0Rubyのバージョンを示しています。Docker Hubでも確認できますが、イメージ本体にも情報がしっかり記されていますね。
このバージョンは重要なので覚えておきましょう。あるいはイメージをpull
する段階で指定してあげてもいいでしょう。BUNDLE_PATH=/usr/local/bundleBundlerのパスが指定されています。Bundlerによる
Gemfile
を使ったGem管理を行えることがわかりますね。ではこのイメージからコンテナを起動しましょう。
適当な名前のディレクトリを作成し、ターミナルの作業フォルダとします。
以降はプロジェクト名をproject_name
とします。
※project_name
以外の名前でも構いません。本記事ではこの名前で統一するということです。rubyイメージからコンテナを起動$ docker run -i -t --name TEST -p 3000:3000 -v "$PWD":/usr/src/project_name ruby /bin/bashまずは各オプションについて。
-i :コンテナのSTDIN(標準入力)にアタッチ。標準入力に入力できる状態にするということ。 -t :疑似ターミナル (pseudo-TTY) を割り当て。ターミナル画面で操作できるようにするということ。 --name :コンテナの名前。今回は'TEST'を指定。 -p :ポートの指定。今回は3000ポートを解放しています。 -v :ボリュームの指定。[ホストPCのディレクトリ指定]:[コンテナ内のディレクトリ指定]。 /bin/bash:コンテナ起動後に実行するコマンド。今回はシェルを指定。上記の説明は簡略したもので語弊を含むので、気になった項目は別途調べることをお勧めします。
-i
と-t
の二つはセットで使う(-it
)ことが多いので是非覚えておきましょう。
ボリュームについては概念が難しいですが、とりあえず[ホストPCで指定したディレクトリ]を[コンテナ内で指定したディレクトリ]として扱えるようにする、程度の理解でいいと思います。参考資料:Dockerリファレンス
うまく起動できたら下のような状態になるはずです。
root@03eb04059b1f:/#
コンテナの中のターミナルを操作しているようなイメージですね。
コンテナの中から一旦抜ける時はcontrol + pq
、再接続するときは$ docker attach [コンテナの指定]
です。
※exit
でも抜けられますが、コンテナが停止してしまうため注意。停止した場合、ポートを閉じてしまうようです。
※$ docker exec
でもコンテナに接続できます。ただし、プロセス接続するごとにプロセスが増えます。仮想環境でRails serverを起動する
それでは今起動したコンテナでRails serverの準備をしましょう。
先ほどコンテナを起動した際に、コンテナ内のproject_name
ディレクトリをボリュームとして指定しました。
指定したディレクトリが作成されているはずなので、そこまで移動しましょう。Railsプロジェクトの確認$ cd /usr/src/project_nameこのディレクトリにRailsプロジェクトを作成していきます。
まずは何をするにもGemfile
が必要なので、Bundlerを使って作成しましょう。Gemfileの作成$ bundle init
次にRailsを導入していきます。
Gemfile
を編集する必要がありますが、これはコンテナ内で行う必要はありません。Gemifile
を作成したディレクトリはコンテナ起動時にホストPC側のディレクトリとセットでボリューム指定したため、ホストPC側の指定したディレクトリにもGemfile
が作成されています。このGemfile
を編集するだけでOKです。Gemfile# frozen_string_literal: true source "https://rubygems.org" git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } - # gem "rails" + gem "rails"コンテナ内のGemfile確認に反映されているか確認$ cat Gemfileこれで
Gemfile
の準備ができたので、GemのインストールとRailsプロジェクトの作成を行いましょう。Gemのインストール$ bundle install $ bundle exec rails new .
rails exec .
は作業ディレクトリに対してRailsプロジェクトを作成します。
実行するとGemfile
の上書き確認をされるので許可しましょう。ローカル環境ではこの時点でRails serverを起動できましたが、
ruby
イメージから作成したコンテナではまだRails serverは起動できません。
ですが、なぜ起動できないか確認するためにも一度試してみましょう。起動確認(失敗する).$ bundle exec rails serverエラーメッセージ(最後のみ抜粋)/usr/src/project_name/vendor/bundle/ruby/2.6.0/gems/execjs-2.7.0/lib/execjs/runtimes.rb:58:in `autodetect': Could not find a JavaScript runtime. See https://github.com/rails/execjs for a list of available runtimes. (ExecJS::RuntimeUnavailable)
ExecJS::RuntimeUnavailable
というエラーについて調べてみると、どうやらJavaScriptランタイムというものが必要のようです。
今回はnode.js
を導入することにしましょう。
参考資料:rails sコマンド実行時に「Could not find a JavaScript runtime.」とエラーが出る場合の対処法
ruby
イメージではyum
コマンドは対応していないようなので、apt-get
を使ってインストールしましょう。
参考資料:apt-get - パッケージの操作・管理 - Linuxコマンドnode.jsのインストール$ apt-get update $ apt-get install nodejs完了したら今度こそRails serverが起動できるはずです。
Rails_server起動$ bundle exec rails serverhttp://localhost:3000/に接続して起動できているか確認しましょう。
dockerfile と docker-compose を使ってコマンド一つでRails serverを起動する
ここからは今まで行ってきたことを設定として文書化していきます。
先ほどまで使用していたコンテナはもう使わないので、$ exit
で停止しておきましょう。
ただし、作成したRailsプロジェクトはそのままにしておいてください。参考資料:Dockerfile リファレンス
参考資料:Compose ファイル・リファレンス
参考資料:RailsアプリをDockerで開発するための手順dockerfile を作成する
まず、前の章で行ったことを整理しておきましょう。
ruby
イメージからコンテナを作成(本記事ではバージョン2.6.0)- ポート3000:3000を開放し、ボリュームを指定してコンテナを起動
- コンテナ内でRailsプロジェクトを作成
- コンテナに
node.js
をインストール- Rails serverを実行
dockerfile
を書くということは、これらの作業を文書化していくということです。それでは
dockerfile
を書いていきます。Railsプロジェクトを作成したディレクトリにdockerfile
という名前でファイルを作成し、編集していきます。
まずは使用したイメージの情報です。dockerfileFROM ruby:2.6.0
:2.6.0
はバージョン情報です。指定しなければ最新版が自動で選択されますが、固定させた方がいいでしょう。
これはRubyのバージョンと同じなので、もし違うバージョンからRailsプロジェクトを作成したならそのバージョンに合わせてください。次にポートの開放とボリューム指定ですが、
dockerfile
ではホストPCのディレクトリを指定することはできません(後でdocker-compose.yml
で指定します)。よって、ここではポートの開放だけを行います。dockerfileFROM ruby:2.6.0 EXPOSE 3000ここでポートの開放を行なっても、
run
コマンドやdocker-compose.yml
で指定しなければ直接接続できないので注意してください。次はコンテナ内でRailsプロジェクト作成ですが、これは後でボリューム指定により共有する予定なので必要ありません。
ですが、Gemfile
が無くてはGemのインストールができず、rails
コマンドが実行できません。
そこで、Gemfile
だけをコンテナ内にコピーしてインストールすることにします。dockerfileFROM ruby:2.6.0 ENV APP_ROOT /usr/src/project_name WORKDIR ${APP_ROOT} COPY Gemfile ${APP_ROOT} COPY Gemfile.lock ${APP_ROOT} RUN bundle install EXPOSE 3000各コマンドは以下の通りです。
ENV [key] [value] …… 環境変数の定義。 WORKDIR [ディレクトリ指定] …… 作業ディレクトリの指定 COPY [ソース指定] [保存先指定] …… ファイルのコピー。 RUN [コマンド] …… コマンドの実行。これでコンテナ内でも
rails
コマンドが利用できるようになります。最後に
node.js
のインストールとRails serverの起動です。dockerfileFROM ruby:2.6.0 ENV APP_ROOT /usr/src/project_name WORKDIR ${APP_ROOT} RUN apt-get update && \ apt-get install -y nodejs COPY Gemfile ${APP_ROOT} COPY Gemfile.lock ${APP_ROOT} RUN bundle install EXPOSE 3000 CMD bundle exec rails serverRailse sever の起動が
RUN
ではなくCMD
なのは、コンテナの立ち上げが完了してから実行してほしいからです。
もしRUN
で書いてしまうとそこで動作が止まってしまい、いつまでもコンテナが立ち上がらないということになってしまいます。では、これでうまく動作するかどうか確認してみましょう。
dockerfileからイメージの作成と起動$ docker build .エラーが出ずにRails serverの起動までできればOKです。
docker-compose.yml を作成し、起動する
では、先ほど作成した
dockerfile
を使ってdocker-compose.yml
を作っていきましょう。
先ほどと同じく、Railsプロジェクトのディレクトリに作成し、以下の通りに編集してください。docker-compose.ymlapp: build: . ports: - '3000:3000' volumes: - .:/usr/src/project_nameapp: …… アプリケーションの名前。今回はappとした。 build: …… docker-composeのパス指定。今回は同一ディレクトリにある。 ports: …… 開放するポートの指定。 volumes: …… ボリュームの指定。これで完了です。では起動してみましょう。
docker-composeからの起動$ docker-compose up -dhttp://localhost:3000/に接続して、いつものアレが表示されたらOKです!
ちなみに、ホストPCのディレクトリを参照しているため、ファイルを編集すると即座に反映されます。Gemfile
と同じですね。おわりに
というわけで、起動できました。とりあえず動いたので満足。