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

さくらVPSにまっさらな状態からRuby2.1.0+Rails4.2.1+nginx+unicorn+capistranoの環境を構築したのでやんわり手順を書いた。

More than 1 year has passed since last update.

さくらVPSを借りてみたのでRailsを動かしてついでに手元のローカル環境で作ったアプリをデプロイ出来るようにしてみました。
完全に初心者なので、細かい所は分かってませんが初心者目線で出来ればと思います。
コピペしていけば構築出来るというサルでき方式を目指して書きました。

登場人物

ruby - rubyこれは知ってた。javaの親戚みたいなやつ
rbenv - rubyのバージョンを選べるようにする便利なやつ
rails - rubyを使ったサイトの構築を簡単に行うやつ
nginx - サーバーソフト?だと思う。こいつがいれば複数のrailsプロジェクトを1つのサーバーで動かせる?っぽい。よくわからないけど人気っぽい
unicorn - rails sで動くやつはWebrickって言うんだけど、それが重いからこれを使うらしい
capistrano - デプロイするやつ。多分gitをサーバー側にcloneしてついでに色々セットアップしてくれている。

さくらVPSの初期化

管理コンソールからOSインストール>標準OSインストール
しばらく待つと使えるようになる。
Updating RPMS on systemと表示されても処理は進んでいるので焦らずに待つ(10分くらい)

定数

以下の解説では下記のように読み替えてください

${IP_ADDRESS} -> 000:00:00:000 (さくらVPSのIP)

${APP_NAME} -> testApp (アプリ名)

${GIT_URL} -> githubのリポジトリのurl。この解説ではrailsにcapistranoのセットアップをする直前にリポジトリを作りますが、タイミングが微妙なので先に作っていてもいいです。

ログイン

Terminal.appを開いて、さくらVPSに繋げる
最初に鍵を作るか聞かれるのでyes
さっきのパスワードでログインする

terminal.app
$ ssh root@${IP_ADDRESS}

サーバーを初期化したりするとIPが一緒なのに鍵が合わなくて怒られるので、その際は鍵を消した後ログイン

terminal.app
$ ssh-keygen -R ${IP_ADDRESS}

rbenvをインストール(server側)

さくらVPS
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv

環境設定の末行に追記する(server側)

~/.bash_profile
export PATH="~/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

~/.bash_profileを再読み込み(server側)

さくらVPS
$ source ~/.bash_profile

ruby_buildをインストール(server側)

さくらVPS
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
さくらVPS
$ sudo ~/.rbenv/plugins/ruby-build/install.sh

ssl(server側)

さくらVPS
$ sudo yum -y install openssl-devel

rubyをインストールする(server側)

少しかかります
readline-develを入れないとエラーが出るようになったのでいれる

さくらVPS
$ yum install -y readline-devel
さくらVPS
$ rbenv install 2.2.2
$ rbenv rehash
$ rbenv global 2.2.2

bundlerのインストール

さくらVPS
$ gem install bundler

SQlite3をインストール(server側)

インストールするか聞かれるので「y」

さくらVPS
$ yum install sqlite-devel

nodejsをインストール(server側)

さくらVPS
$ yum install nodejs npm --enablerepo=epel

nginxをインストール(server側)

さくらVPS
$ sudo yum install -y nginx

nginxのセットアップ(server側)

/etc/nginx/conf.d/local.conf
upstream unicorn {
  server unix:/var/www/app/${APP_NAME}/current/tmp/unicorn.sock;
}

server {
  listen 80 default_server;

  access_log /var/log/nginx/sample_access.log;
  error_log /var/log/nginx/sample_error.log;

  root /var/www/app/${APP_NAME}/current;

  client_max_body_size 100m;
  error_page 404 /404.html;
  error_page 500 502 503 504 /500.html;
  try_files $uri/index.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_pass http://unicorn;
  }
}

--

以下はクライアント(Mac側)

railsプロジェクト作る

terminal.app
$ rails new sample

プロジェクト修正

Gemfile
gem 'rb-readline'
gem 'unicorn'
gem 'capistrano'
gem 'capistrano-rails'
gem 'capistrano-bundler'
gem 'capistrano-rbenv', github: "capistrano/rbenv"

terminal.app
$ bundle install --path ./vendor/bundle

サブドメイン設定。
やってもやらなくてもいい。やるとdomain.com/${APP_NAME}/がルートになる。
名前の前の/わすれ注意

config.ru
# This file is used by Rack-based servers to start the application.
RAILS_RELATIVE_URL_ROOT="/${APP_NAME}"
require ::File.expand_path('../config/environment',  __FILE__)
if RAILS_RELATIVE_URL_ROOT then
        map RAILS_RELATIVE_URL_ROOT do
                run Rails.application
        end
else
        run Rails.application
end

unicornのセットアップ

./config/unicorn.rb(新規作成)
# -*- coding: utf-8 -*-
worker_processes 2

listen  Dir.pwd + '/tmp/unicorn.sock'
pid     Dir.pwd + '/tmp/unicorn.pid'

log = Dir.pwd + '/log/unicorn.log'
stderr_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])
stdout_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])

preload_app true
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true

before_fork do |server, worker|
defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!

old_pid = "#{ server.config[:pid] }.oldbin"
unless old_pid == server.pid
  begin
   sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
   Process.kill :QUIT, File.read(old_pid).to_i
   rescue Errno::ENOENT, Errno::ESRCH
  end
end
end

after_fork do |server, worker|
    defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end

スクリプト用ディレクトリを作る

terminal.app
$ mkdir script
script/unicorn
#!/bin/bash

set -e

TIMEOUT=${TIMEOUT-60}
APP_ROOT=$PWD
PID="$APP_ROOT/tmp/unicorn.pid"
#RAILS_ENV=production
RAILS_ENV=development
CMD="bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb -E $RAILS_ENV"
action="$1"
set -u

old_pid="$PID.oldbin"

cd $APP_ROOT || exit 1

sig () {
    test -s "$PID" && kill -$1 `cat $PID`
}

oldsig () {
    test -s $old_pid && kill -$1 `cat $old_pid`
}

case $action in
start)
    sig 0 && echo >&2 "Already running" && exit 0
    $CMD
    ;;
stop)
    sig QUIT && rm -f ${PID} && exit 0
    echo >&2 "Not running"
    ;;
force-stop)
    sig TERM && exit 0
    echo >&2 "Not running"
    ;;
restart|reload)
    sig HUP && echo reloaded OK && exit 0
    echo >&2 "Couldn't reload, starting '$CMD' instead"
    $CMD
    ;;
upgrade)
    if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
    then
        n=$TIMEOUT
        while test -s $old_pid && test $n -ge 0
        do
            printf '.' && sleep 1 && n=$(( $n - 1 ))
        done
        echo

        if test $n -lt 0 && test -s $old_pid
        then
            echo >&2 "$old_pid still exists after $TIMEOUT seconds"
            exit 1
        fi
        exit 0
    fi
    echo >&2 "Couldn't upgrade, starting '$CMD' instead"
    $CMD
    ;;
reopen-logs)
    sig USR1
    ;;
*)
    echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
    exit 1
    ;;
esac

権限を付与

terminal.app
$ sudo chmod 755 ./script/unicorn

git

githubなどにrailsアプリ全体をpushする。
この後設定するcapistranoでそのgitのurlを使う。
また、デプロイの際はこのリポジトリにpushしたあとにデプロイする

capistrano

terminal.app
$ cap install
Capfile
require 'capistrano/setup'

require 'capistrano/deploy'

require 'capistrano/rbenv'
set :rbenv_type, :user
set :rbenv_ruby, '2.1.0'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'

Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r }

修正箇所3箇所

config/deploy.rb
lock '3.4.0'

set :application, '${APP_NAME}'
set :repo_url, '${GIT_URL}'

set :branch, 'master'
set :deploy_to, '/var/www/app/${APP_NAME}'
set :scm, :git
set :log_level, :debug
set :pty, true

set :bundle_binstubs, nil
set :linked_dirs, %w{log tmp/pids tmp/cache tmp/sockets bundle public/system public/assets}
set :default_env, { path: "/usr/local/rbenv/shims:/usr/local/rbenv/bin:$PATH" }
set :keep_releases, 5

namespace :deploy do
  after :finishing, 'deploy:cleanup'
end
config/deploy/development.rb
set :stage, :development
role :app, %w{root@${IP_ADDRESS}}
role :web, %w{root@${IP_ADDRESS}}
role :db, %w{root@${IP_ADDRESS}}

server '${IP_ADDRESS}',
user: 'root',
roles: %w{web app db},
ssh_options: {
 auth_methods: %w(password),
 password: '********'
}

githubへpushして上記のconfig/deploy.rbを対応させる

デプロイ

少しかかる
:terminal.app
$ cap development deploy

サーバー起動

さくらVPS
$ cd /var/www/app/${APP_NAME}/current
$ ./script/unicorn start
$ sudo service nginx start

付録

覚えておくと捗るコマンド

ps aux | grep ${process_name}
${process_name}が含まれるプロセスを表示。

kill process_id
さっきので取得したprocess_idを入れると殺せる

cd
階層の移動

vim ${filename}
エディタ。iとesc>ZZさえ出来ればOK

ls
現階層のファイル一覧表示

pwd
現階層までのパスを表示。かわいい

それでも出来ない

scale使おう

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
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