Help us understand the problem. What is going on with this article?

【Ruby】Sinatraで、速攻でWebサイトを公開するための環境構築

More than 5 years have passed since last update.

初めて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)にしました。

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

    # '/'にアクセスした時の処理
    # 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個のホストを設定した場合を記述しています。

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サーバを再起動しないと反映されないため、開発環境では自動でリロードされるように設定。

Apache+Passengerの場合

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環境の時のみ実行されるような分岐を書いておく。

Basic認証

ついでにベーシック認証についても調べたので書いておく。

サイト全体にかける場合
main.rb
# ルーティングファイルの最初に記述
use Rack::Auth::Basic do |username, password|
    username == "name" && password == "passwd"
end
特定のパスにかける場合
main.rb
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"

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした