はじめに
(初心者向け)vpsを契約して、capistrano3でRailsアプリをデプロイするまで [その1 サーバー設定編] の続きです。
前回でサーバーの設定は一通り完了したので、こちらでは、デプロイするテストアプリの構築、Capistrano、Unicornの設定を行います。
1. Railaアプリの作成
Rilsチュートリアルの第2章に習ってscaffoldでユーザー名簿のアプリを作成します。
Rubyのインストール、Railsのインストールは省略します。
1-1 アプリの構築
Rails newで構成を作ります。
以下全てローカルです。任意のディレクトリで始めてください。
# Railsディレクトリの構築
$ rails new hoge_app
$ cd hoge_app
# gemのインストール
$ bundle install
1-2 model、view、controllerの作成
アプリ作成自体はこの記事の主ではないので、簡単にscaffoldで作成します。
# MVCの一括作成
$ rails generate scaffold User name:string email:string
# dbのmigrate
$ rails db:migrate
1-3 ルーティングの設定
このままだとroot(ipアドレス直下)で何が表示されるか設定されいないので、ルーティングを設定します。
config/routes.rbを開いて
$ vi config/routes.rb
以下の用にroot to:を追加してください
Rails.application.routes.draw do
resources :users
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root to: 'users#index'
end
1-4 起動確認
rails serverで以下画面が表示されればとりあえずアプリは完成です。
# サーバーの起動
$ rails s
http://0.0.0.0:3000/
にアクセス
1-3 データベースの設定
Rails newで作成したデフォルトの設定では、データベースがSQLiteとなっています。今回サーバー側では、MySQLを使用しますので、その設定を行います。
config/database.ymlを開いて
$ vi config/database.yml
default: &default
adapter: sqlite3
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000
development:
<<: *default
database: db/development.sqlite3
test:
<<: *default
database: db/test.sqlite3
# ここから変更
production:
adapter: mysql2
encoding: utf8
pool: 5
database: hoge_app_production
username: root
password: root # その1で設定したサーバー側のmysqlのパスワード
socket: /var/lib/mysql/mysql.sock
データベースの作成自体は後ほどcapistranoで行います。
次にproductionでSQLiteを使用しないので、Gemfileを修正します。
$ vi Gemfile
groupでくくられていないgem ’sqlite3’をコメントアウトし、developmentのグループのなかに’sqlite3’を追加します。
さらにproductionのグループを追記し、そちらにmysql2を設定しています。
.
.
# Use sqlite3 as the database for Active Record
# gem 'sqlite3' コメントアウト
.
.
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]
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '~> 2.13'
gem 'selenium-webdriver'
# 追加
gem 'sqlite3'
end
.
.
# 以下追加
group :production, :staging do
gem 'mysql2'
end
編集終わったらインストール
$ bundle install
1-4 バージョン管理の開始
Capistranoではgithubを介したデプロイを行うので、githubのremoteリポジトリの登録とpushを行います。
# バージョン管理の開始
$ git init
# 変更履歴のコミット
$ git add . && git commit -m 'first commit'
# リモートリポジトリの登録(事前にご自身のgithubでリポジトリを作っておいてください)
# リポジトリ追加の際に表示される案内に従ってコマンドを入力
$ git remote add origin git@github.com:kawamataryo/hogeapp.git
# リモートへのアップ
$ git push -u origin master
2. Capistranoの設定
Capistranoとは、Ruby製のデプロイツールです。
デプロイツールとは、ローカルで開発していたアプリを、ステージング、プロダクションのサーバーにアップロードする様々な操作を自動化するものです。例えば、更新ファイルの転送、DBのmigrationの実行、NginxやUnicornの再起動、バージョン管理、複数サーバーへのデプロイなどを1コマンドで実行することができます。
これから出てくるCapistranoの設定方法については主に以下記事を参考にさせて頂きました。
(Capistrano編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで - Qiita
2-1 Gemの追加
Capistranoの関連Gemをインストールします。
$ vi Gemfile
developのグループにcapistrano関連のgem、とproducitonのグループにunicornのgemを追加してください。
group :development do
# Access an IRB console on exception pages or by using <%= 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'
# 以下追記
gem 'capistrano'
gem 'capistrano-bundler'
gem 'capistrano-rails'
gem 'capistrano-rbenv'
end
group :production, :staging do
gem 'mysql2'
# 以下追記
gem 'unicorn'
end
追加したらインストール!
$ bundle install
これで今回のデプロイで使うgemが全てインストールされました。
2-2 capistranoの設定ファイル生成
新たにcapコマンドが使えるのでそれでcapistranoの設定ファイルを作成します。
$ bundle exec cap install
以下のようなファイルが生成されます。
hogeapp
├─ Capfile
├─ config
│ ├─ deploy
│ │ ├─production.rb
│ │ └─staging.rb
│ └─deploy.rb
└─ lib
└─capistrano
└─tasks
2-3 capistranoの基本設定
capistranoの設定ファイルを編集します。
ます、何を読み込むか、Capistranoでどどのような動作を行うかに合わせて決めます。
$ vi capfile
最初に記載されている内容は削除で大丈夫です。
今回は下の用に設定しましょう。
require hogehogeの部分で読み込むファイルを設定しています。
require "capistrano/setup"
require "capistrano/deploy"
require "capistrano/rbenv"
require "capistrano/bundler"
require "capistrano/rails/assets"
require "capistrano/rails/migrations"
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git
# taskを記述したファイルを読み込む用に設定。
# なおデフォルトでは *.rakeとなっているのでもとの記述をそのまま使う場合は注意!!
Dir.glob("lib/capistrano/tasks/*.rb").each { |r| import r }
2-4 productionの環境設定
2-2で生成したconfig/deploy配下にあるprouction.rbにサーバーの情報を記述します。ちなみにstaging.rbはその名の通り、ステージングの情報です。
vi config/deploy/production.rb
こちらも元のコードは全削除で大丈夫です。
# conohaのサーバーのIP、ログインするユーザー名、サーバーの役割
# xxxの部分はサーバーのIPアドレス
# 10022はポートを変更している場合。通常は22
server 'xxx.xxx.xxx.xxx', user: 'hoge', roles: %w{app db web}, port: 10022
#デプロイするサーバーにsshログインする鍵の情報。サーバー編で作成した鍵のパス
set :ssh_options, keys: '~/.ssh/conoha_hoge/id_rsa'
次にproductionとstaging共通の設定について、
deploy.rbに記述します。
$ vi config/deploy.rb
こちらも最初の記述は全削除で。
※ capistranoのバージョンは確認して、以下記述のバージョンを調整してください。
rubyのバージョンからアプリケーション名、デプロイで送るgithubのリポジトリ、capistranoのタスクなどを記述します。
# capistranoのバージョン固定
lock "~> 3.10.1"
# デプロイするアプリケーション名
set :application, 'hoge_app'
# cloneするgitのレポジトリ
# 1-3で設定したリモートリポジトリのurl
set :repo_url, 'git@github.com:kawamataryo/hogea_pp.git'
# deployするブランチ。デフォルトはmasterなのでなくても可。
set :branch, 'master'
# deploy先のディレクトリ。
set :deploy_to, '/var/www/hoge_app'
# シンボリックリンクをはるファイル
set :linked_files, fetch(:linked_files, []).push('config/secrets.yml')
# シンボリックリンクをはるフォルダ
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')
# 保持するバージョンの個数(※後述)
set :keep_releases, 5
# rubyのバージョン
# rbenvで設定したサーバー側のrubyのバージョン
set :rbenv_ruby, '2.4.1'
# 出力するログのレベル。
set :log_level, :debug
# デプロイのタスク
namespace :deploy do
# unicornの再起動
desc 'Restart application'
task :restart do
invoke 'unicorn:restart'
end
# データベースの作成
desc 'Create database'
task :db_create do
on roles(:db) do |host|
with rails_env: fetch(:rails_env) do
within current_path do
# データベース作成のsqlセット
# データベース名はdatabase.ymlに設定した名前で
sql = "CREATE DATABASE IF NOT EXISTS hoge_app_production;"
# クエリの実行。
# userとpasswordはmysqlの設定に合わせて
execute "mysql --user=root --password=root -e '#{sql}'"
end
end
end
end
after :publishing, :restart
after :restart, :clear_cache do
on roles(:web), in: :groups, limit: 3, wait: 10 do
end
end
end
参考に上げた
(Capistrano編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで - Qiita
に詳細説明あるので、ここでは各パラメーターの説明は省略します。
2-5 環境変数の設定(サーバー側)
2-4で上げたdeploy.rbの設定において以下記述があります。
# シンボリックリンクをはるファイル
set :linked_files, fetch(:linked_files, []).push('config/secrets.yml')
これはRailsで使用するsecrets.ymlはここを読み込んでねというリンクを設定している記述です。
まだ、サーバー側でsecrets.ymlを作成していないので、そちらを作りましょう。
まず、ローカルで乱数を作成します。
rake secretで乱数を生成、それをpbcopyでクリップボードにコピーしています。
# 以下ローカルのRailsディレクトリで実行してください
$ rake secret | pbcopy
次はサーバー側 での処理です。
sshでサーバーにログインして、ディレクトリとファイルの作成を行います。
# サーバーログイン
$ ssh conoha_hoge
# ディレクトリの作成
$ cd /var
$ sudo mkdir -p www/hoge_app/shared/config
# 所有者を設定
$ sudo chown -R hoge www
# ファイルの作成
$ cd www/hoge_app/shared/config
$ sudo vi secrets.yml
secrets.ymlには以下を記述してください。
secret_key_baseの値の乱数の部分は先程コピーしたものです。
production:
secret_key_base: jr934ugr89vwredvu9iqfj394vj9edfjcvnxii90wefjc9weiodjsc9oi09fiodjvcijdsjcwejdsciojdsxcjdkkdsv
これで環境変数の設定は完了です。
なおsecret_key_baseは、クッキーの暗号化、復号化に使用するようです。
以下参考
Rails secret_key_baseとは何なのか - Qiita
2-6 unicornの設定
アプリケーションサーバーであるunicornのセットアップタスクを記述します。
capistranoでユニコーンを操作するためのたタスクです。
NginxとUnicornの関係が気になる方は、以下を読みましょう。
Rails開発におけるwebサーバーとアプリケーションサーバーの違い(翻訳) - Qiita
以下作業は全てローカルです、
# railsアプリのディレクトリにて
$ vi lib/capistrano/tasks/unicorn.rb
作成したunicorn.rbには以下のように記述しましょう
こちらも、以下記事参考にさせて頂きました。
(Capistrano編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで - Qiita
各設定の意味まで詳細に解説してくださっているので大変参考になります。
#unicornのpidファイル、設定ファイルのディレクトリを指定
namespace :unicorn do
task :environment do
set :unicorn_pid, "#{current_path}/tmp/pids/unicorn.pid"
set :unicorn_config, "#{current_path}/config/unicorn/production.rb"
end
#unicornをスタートさせるメソッド
def start_unicorn
within current_path do
execute :bundle, :exec, :unicorn, "-c #{fetch(:unicorn_config)} -E #{fetch(:rails_env)} -D"
end
end
#unicornを停止させるメソッド
def stop_unicorn
execute :kill, "-s QUIT $(< #{fetch(:unicorn_pid)})"
end
#unicornを再起動するメソッド
def reload_unicorn
execute :kill, "-s USR2 $(< #{fetch(:unicorn_pid)})"
end
#unicronを強制終了するメソッド
def force_stop_unicorn
execute :kill, "$(< #{fetch(:unicorn_pid)})"
end
#unicornをスタートさせるtask
desc "Start unicorn server"
task start: :environment do
on roles(:app) do
start_unicorn
end
end
#unicornを停止させるtask
desc "Stop unicorn server gracefully"
task stop: :environment do
on roles(:app) do
stop_unicorn
end
end
#既にunicornが起動している場合再起動を、まだの場合起動を行うtask
desc "Restart unicorn server gracefully"
task restart: :environment do
on roles(:app) do
if test("[ -f #{fetch(:unicorn_pid)} ]")
reload_unicorn
else
start_unicorn
end
end
end
#unicornを強制終了させるtask
desc "Stop unicorn server immediately"
task force_stop: :environment do
on roles(:app) do
force_stop_unicorn
end
end
end
続いて、unicornの設定ファイルを作成します。
まずファイルの新規作成
$ mkdir config/unicorn
$ vi config/unicorn/production.rb
ファイルの中身については以下のように記述しましょう。
#ワーカーの数
$worker = 2
#何秒経過すればワーカーを削除するのかを決める
$timeout = 30
#自分のアプリケーション名、currentがつくことに注意。
$app_dir = "/var/www/hoge_app/current"
#リクエストを受け取るポート番号を指定。後述
$listen = File.expand_path 'tmp/sockets/.unicorn.sock', $app_dir
#PIDの管理ファイルディレクトリ
$pid = File.expand_path 'tmp/pids/unicorn.pid', $app_dir
#エラーログを吐き出すファイルのディレクトリ
$std_log = File.expand_path 'log/unicorn.log', $app_dir
# 上記で設定したものが適応されるよう定義
worker_processes $worker
working_directory $app_dir
stderr_path $std_log
stdout_path $std_log
timeout $timeout
listen $listen
pid $pid
#ホットデプロイをするかしないかを設定
preload_app true
#fork前に行うことを定義
before_fork do |server, worker|
defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
old_pid = "#{server.config[:pid]}.oldbin"
if old_pid != server.pid
begin
Process.kill "QUIT", File.read(old_pid).to_i
rescue Errno::ENOENT, Errno::ESRCH
end
end
end
#fork後に行うことを定義
after_fork do |server, worker|
defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end
3. githubへのpush
あともう少しでデプロイ完了です。
capistranoはgithubを介してサーバーにファイルを送ります。
なので今までの変更をgithubへpushしましょう。
# 変更履歴をステージング
$ git add .
# コミット
$ git commit -m 'config complete'
# githubへ送信
$ git push origin master
4. サーバーへのデプロイ
いよいよ最後。capistranoでサーバーにデプロイします。
4-1 サーバーにてアプリの用のDB作成
いざデプロイ!と実行したいのですが、まだサーバーにアプリ用のデータベースを作成していません。なので最初はサーバーのデータベース作成を行います。
おそらく私の手順が悪いのですが、少し面倒な手順をおいます。
まず、サーバー側にアクセスしvar/www/hoge_app/currentディレクトリを作成
$ ssh conoha_hoge
# 以下サーバー側にて
$ mkdir /var/www/hoge_app/current
$ exit
次にローカル側でcapistranoのタスクに登録していたコマンドを実行
$ bundle exec cap production deploy:db_create
これでDBを作成できました。
次にdeployでエラーを出さないように先程作成したサーバー側のcurrentディレクトリを削除します。
$ ssh conoha_hoge
# 以下サーバー側にて
$ sudo rm -r /var/www/hoge_app/current
$ exit
なぜこのような手順を追うかと言うと、deploy:db_createではcurrentがないとエラー。deployだとcurrentがあるとエラー。という状況にあたったからです。
もし最適な方法が分かる方いましたらコメントにて指摘お願いします。
4-2 デプロイの実行
長くなりましたがやっとデプロイです!!以下コマンドでデプロイが成功するはず!!
初回はrbenvのところで少し時間がかかるかと思います。
$ bundle exec cap production deploy
4-3 Nginxの起動
まだNginxが起動していないので、
サーバーにアクセスし、Nginxを起動しましょう。
# サーバーへログイン
$ ssh conoha_hoge
Nginxの起動
$ sudo service nginx start
$ exit
4-4 サイト確認
何事もなく完了したらサイトにアクセスしてみましょう。
$ open http://xxx.xxx.xxx.xxx # conohaのipアドレス
無事表示されればデプロイ完了です!!
最後に
私は、独学でプログラミングを学びRailsチュートリアルを参考にwebアプリを作成しました。
でもデプロイの段階で困り果て、VPSって何?なんか勝手にお金かかりそうで怖い!なんで最初からサーバーの入ってないの?っとかなり及び腰でした。
しかし、先人の方々の記事を参考に進めた所、つまづきつまづきエラーとにらめっこしながらですが、なんとかアプリ運用までたどり着きました。
今回の経験で学んだことは、
- エラーメッセージは怖くない!(英語でちゃんと理由を説明してくれているので)
- 設定ファイルはしっかり理解しよう!(コピペだとエラーのデバック時時間が無限にかかります涙)
- デプロイできるとものすごく嬉しい!(重要!)
ということです。
自分と同じように自作アプリをデプロイしようとする方の参考になれば幸いです。
また、こんなエラーが出てデプロイ出来ない!typoがある!こっちのほうが良い方法だ!という意見・質問等ございましたらコメント・編集リクエストお願いします。
出来る限り答えていきます。