初めてSinatraでアプリを作ったので覚えたことをまとめました。とにかくWebサイトを公開するために必要なことだけが書かれています。
私の環境が事情によりローカル環境:Apach + Passenger、リモート環境:Nginx + Unicornなので、一応両方で動くようまとめ・・・たつもりです。
qiitaにも投稿しているので、ストックする場合はこちら。
AWSの環境構築についてはこちら。
SinatraでDBを扱う場合はこちらもどうぞ。
最小構成は下記。
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の設定ファイル
プロジェクト直下にconfig.ruを置きます。
また今回はControllerを別ファイル(main.rb)にしました。
#config.ru require './main.rb' run MainApp
#main.rb 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 # '/'にアクセスした時の処理 get '/' do haml :index # views/index.haml hamlのテンプレート end end
Sinatraのコントローラで、URLの設定をしていきます。
%r{^/(.*)\.css$} の()の部分は params[:captures] という配列に格納されるようで、firstで0番目の要素を取得します。
つまりこの場合、/base.css にアクセスすると、views以下にある style/base.scss が呼び出されます。
肝心のSinatraですが、基本はこれだけ。超簡単です。
Railsではおなじみですが、Sinatraでもgemの管理にbundlerを使ってみます。
# インストール $ gem install bundler $ cd projectname $ bundle init # Gemfileが作成される
#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
静的なサイトと同様、サイト数分、VirtualHostブロックを追加するだけです。
私のUbuntuのApacheはバーチャルホストの設定ファイルがconfigとは別ファイルになっていました。環境によっては少し違うと思われます。
$ cd /etc/apache2/sites-available/ $ sudo vim projectname-test # 既存のプロファイルをコピーでもおk
# configファイル # プロジェクトディレクトリ以下の 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をリバースプロキシとして設定します。
Nginx設定ファイルの中に、サイトの数分、upstreamブロックとlocationブロックを増やします。下記では2個のアプリに2個のホストを設定した場合を記述しています。
# nginx.conf # 下記を追記 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を編集します。
# 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サーバを再起動しないと反映されないため、開発環境では自動でリロードされるように設定。
# tmp/always_restart.txt # tmp/以下に always_restart.txt を置くだけ。中身は空でOK
gem install sinatra-contrib
# main.rb require "sinatra/reloader" # if development? などの条件分岐をつけておく
Gitでデプロイする場合には、.gitignoreに上記txtファイルを追加 or dev環境の時のみ実行されるような分岐を書いておく。
ついでにベーシック認証についても調べたので書いておく。
# main.rb # ルーティングファイルの最初に記述 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’]の値で分岐しました。
# cmd # sinatraの中で分岐する場合は以下の定数が使える ENV['RACK_ENV'] # "development" or "production" # rubyを実行する場合、オプションを付ける # dev環境 $ RACK_ENV=development ruby app/dataset.rb # production環境 $ RACK_ENV=production ruby app/dataset.rb
今回勉強も兼ねてSinatraを選択したのですが、そういう意味ではRailsよりも良いです。コアとなる処理は自分で書かなきゃなりませんし、ActiveRecord無しの場合はSQL文も書く必要ありますし。また、ページ数の少ないアプリをさくっと作るには、Railsよりも全然素早く作成&公開できます。あんてなサイトやクローラを使ったサービスのような、シングルページのWebサービス量産には持ってこいですね。
Nginxの設定まわりについても色々調べたので、次回はNginxのことをまとめようと思います。
どちらも良書です。オライリーのSinatraはKindle版もあります。