初めてSinatraでアプリを作ったので覚えたことまとめ。
事情によりローカルはApach + Passenger、リモートはNginx + Unicornなので、一応両方で動くようまとめ・・・たつもりなのですが。
元記事
下記エントリの転載になります。
【Ruby】Sinatraで、速攻でWebサイトを公開するための環境構築 - rokuroFire
事前準備
- Ruby、bundlerのインストール
- Apacheの場合、Passengerの設定をしておく
- Nginxの場合、Unicornのgemをインストールしておく
アプリのファイル構成
最小構成は下記。
projectname/
-main.rb // Controller
-config.ru // Rackの設定ファイル。最初に実行されるファイル
-views/
-index.haml // ビューのテンプレート(haml)ファイル
-public/ // webサーバのドキュメントルートはここを指定。画像もここ
個人的に、作業ディレクトリは下記のようにしてみました
projectname/
-Gemfile
-config.ru // Rackの設定ファイル。最初に実行されるファイル
-main.rb // Controller
-app/ // 何らかの処理
-module/ // モジュール類のファイル
-views/ // ビューのテンプレート(haml)ファイル
-index.haml
-layout.haml
-style/ // sass(scss)ファイル
-baes.scss
-db/ // データベースの設定ファイル(yml)を置く
-log/ // ログ置き場
-public/ // webサーバのドキュメントルートはここを指定。画像もここ
-tmp/
-vendor/
-bundle/ // gemの管理ディレクトリ
-unicorn.rb // unicornの設定ファイル
Sinatraの設定
プロジェクト直下にconfig.ruを置きます。
また今回はControllerを別ファイル(main.rb)にしました。
require './main.rb'
run MainApp
require 'rubygems'
require 'sinatra/base'
require 'logger'
require 'unicorn'
require 'haml'
require 'sass'
# config.ru ではこのクラスをrunしています
class MainApp < Sinatra::Base
# cssにアクセスした時の処理
get %r{^/(.*)\.css$} do
scss :"style/#{params[:captures].first}" #scssテンプレート
end
# '/'にアクセスした時の処理
# views/index.haml
get '/' do
haml :index #views/index.haml(hamlのテンプレート)
end
end
%r{^/(.*).css$} の()の部分は params[:captures] という配列に格納されるようで、firstで0番目の要素を取得します。
つまりこの場合、/base.css にアクセスすると、views以下にある style/base.scss が呼び出されます。
bundlerでgemの管理
Railsではおなじみですが、Sinatraでもgemの管理にbundlerを使ってみます。
# インストール
$ gem install bundler
$ cd projectname
$ bundle init
# Gemfileが作成される
source "https://rubygems.org"
gem 'sinatra'
gem 'haml'
gem 'mysql2'
gem 'activerecord'
gem 'unicorn' # Nginx + Unicornの場合
・・・# などなど
#【注意】
# gemは "activerecord"
# .rb内でのrequireは "active_record"
# gemを入れるディレクトリを作成
mkdir vendor
mkdir vendor/bundle
# パスを指定して bundle install
# bundle exec をつけることで、Gemfileで指定されたgem環境でコマンドが実行される
$ bundle install --path vendor/bundle
# リモートのUnicornのバージョンを調べるなど
$ bundle exec unicorn -v
unicorn v4.7.0
##Webサーバ(バーチャルホスト)の設定
#####Apache x passengerの場合
静的なサイトと同様、サイト数分、VirtualHostブロックを追加するだけです。
私のUbuntuのApacheはバーチャルホストの設定ファイルがconfigとは別ファイルになっていました。環境によっては少し違うと思われます。
$ cd /etc/apache2/sites-available/
$ sudo vim projectname-test # 既存のプロファイルをコピーでもおk
# プロジェクトディレクトリ以下の public を指定する
# 今回は /var/www/hogehoge/projectname/ がプロジェクトディレクトリ
<VirtualHost *:80>
RailsEnv development
ServerName local.projectname.com
DocumentRoot /var/www/hogehoge/projectname/public
<Directory /var/www/hogehoge/projectname/public>
Options Indexes -MultiViews MultiViews Includes FollowSymLinks
AllowOverride all
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
sudo a2ensite projectname-test
// apacheは自動で再起動される
Nginx x unicornの場合
Nginxをリバースプロキシとして設定します。
Nginx設定ファイルの中に、サイトの数分、upstreamブロックとlocationブロックを増やします。下記では2個のアプリに2個のホストを設定した場合を記述しています。
#下記を追記
worker_processes 1;
events {
worker_connections 1024;
}
http {
#アプリ1
upstream app1 {
server unix:/tmp/app1.sock;
}
#アプリ2
upstream app2 {
server unix:/tmp/app2.sock;
}
#アプリ1
server {
listen 80;
server_name local.projectname.com;
location / {
root /var/www/hogehoge/projectname/public;
proxy_pass http://app1; #unicornのupstreamを指定
proxy_set_header Host $host;
}
}
#アプリ2
server {
listen 80;
server_name local.projectname2.com;
location / {
root /var/www/hogehoge/projectname2/public;
proxy_pass http://app2; #unicornのupstreamを指定
proxy_set_header Host $host;
}
}
}
unicornの設定ファイル unicorn.rbを編集します。
# coding: utf-8
# プロジェクトディレクトリへのパス
@path = "/var/www/hogehoge/projectname/"
worker_processes 1 # CPUのコア数に揃える
working_directory @path
timeout 300
listen '/tmp/app1.sock' # Nginxのconfig内にあるupstreamで、このパスを指定
pid "#{@path}tmp/pids/unicorn.pid" # pidを保存するファイル
# logを保存するファイル
stderr_path "#{@path}log/unicorn.stderr.log"
stdout_path "#{@path}log/unicorn.stdout.log"
preload_app true
unicornの起動コマンド
$ bundle exec unicorn -E production -c unicorn.rb -D
# unicorn.rbのあるアプリディレクトリで上記実行
# -E で環境を指定、-D でデーモン化
# bundlerを利用している場合には bundle exec
# unicornを停止する場合は、pidを調べてkillする
ここまでで、とりあえずSinatraでWebサイトを公開することが出来ると思います。
自動リロード
通常、アプリケーションファイルを変更してもWebサーバを再起動しないと反映されないため、開発環境では自動でリロードされるように設定。
####Apache+Passengerの場合
# tmp/以下に always_restart.txt を置くだけ。中身は空でOK
####それ以外の場合
gem install sinatra-contrib
require "sinatra/reloader"
# if development? などの条件分岐をつけておく
Gitでデプロイする場合には、.gitignoreに上記txtファイルを追加 or dev環境の時のみ実行されるような分岐を書いておく。
Basic認証
ついでにベーシック認証についても調べたので書いておく。
サイト全体にかける場合
# ルーティングファイルの最初に記述
use Rack::Auth::Basic do |username, password|
username == "name" && password == "passwd"
end
特定のパスにかける場合
helpers do
def protected!
unless authorized?
response['WWW-Authenticate'] = %(Basic realm="Restricted Area")
throw(:halt, [401, "Not authorized\n"])
end
end
def authorized?
@auth ||= Rack::Auth::Basic::Request.new(request.env)
@auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == ['name', 'passwd']
end
end
get /protectedurl do
protected!
"ベーシック認証ページですよ"
end
環境の変更
# sinatraの中で分岐する場合は以下の定数が使える
ENV['RACK_ENV'] # "development" or "production"
# Sinatraとは別にrubyの処理をコマンドラインで叩く場合、オプションを付ける
# dev環境
$ RACK_ENV=development ruby app/dataset.rb
# production環境
$ RACK_ENV=production ruby app/dataset.rb
同様の定数に環境名が入るので分岐に使える
ENV['RACK_ENV'] # "development" or "production"
##参考