ホーム > カテゴリ > Ruby・Ruby on Rails >

Nginx/Unicorn/Ruby on Railsの本番環境構築/デプロイ [CentOS]

CentOSで各種サーバー構築(目次)

CentOS6/7に「Nginx」(Webサーバー)、「Unicorn」(アプリケーションサーバー)、「PostgreSQL」(データベース)の環境を構築して「Ruby on Rails」のプロジェクトをデプロイ(Web上に公開)する方法です。

この記事のVPS(仮想専用サーバ)ではConoHaを利用していますが、さくらのVPS、AWSなどでも同じように構築できると思います。OS以外、新規にインストールしますが「初心者」でもOKです。

実行例

Nginxのインストール直後は/usr/share/nginx/html/index.htmlを表示。

最終的にはRailsプロジェクトを表示します。

目次

1. 契約/サービスお申込み
2. 一般ユーザーを追加/sudoを設定する
3. テキストエディタviの使い方
4. 一般ユーザーで公開鍵認証 (rootログイン禁止/パスワードログイン禁止)
5. SSHポート変更 &ファイアウォールの設定(firewalld)
6. SFTPの設定(WinSCP)
7. git/rbenv/Ruby/Railsのインストール
8. PostgreSQLのインストール
9. Nginxのインストール
10. Railsプロジェクトの作成
11. unicorn.rbを作成する
12. Unicornの起動/停止スクリプトを作成する (CentOS6)
13. /myapp/lib/tasks/unicorn.rakeを編集する (CentOS6)
14. /myapp/publicにindex.htmlを作成する
15. Nginxの設定ファイル(nginx.conf)の編集
16. myapp.confを作成する
17. Nginx、Unicornを手動で起動/停止
18. Nginxの自動起動
19. Unicornの自動起動
20. 自動起動の確認
21. イメージの保存

以下、解説がない章は参考URLを見て下さい。 ※ConoHaの公式サイト。

1. 契約/サービスお申込み

ConoHaのVPSサービスに申し込みます。

1サービスを選択(最初は1GBメモリ推奨。後でスケールアップ/ダウン可能)
2イメージタイプは[OS]タブの「CentOS」の7.6を選択
3rootパスワードを入力
4[オプションを見る][スタートアップスクリプト][テンプレート]の「Fail2banインストール」を選択
5追加ボタンを押せばサーバーが作成されます。

※Fail2banはブルートフォース攻撃(総当たり攻撃)の対策です。

2. 一般ユーザーを追加/sudoを設定する

3. テキストエディタviの使い方

これだけ使えればOKです。

i編集モードの開始 ※「i」は小文字のアイ。
ESC編集モードの終了
Back Space編集モードで1文字の削除 ※Deleteは不可
/検索文字 + Enter閲覧モードで文字列を検索可能
:wq + Enter保存して終了
:q! + Enter保存せずに終了 ※「!」はビックリマーク。

4. 一般ユーザーで公開鍵認証 (rootログイン禁止/パスワードログイン禁止)

※ユーザー名、秘密鍵のパスフレーズ、秘密鍵でのログインとなります。

5. SSHポート変更 &ファイアウォールの設定(firewalld)

firewalldによる各ポートの制御でセキュリティを高めます。

この5章からのコマンドは、2章で追加した一般ユーザーでログインしてから行います。

// 状態を確認
sudo firewall-cmd --list-all

// sshd_configの編集
sudo vi /etc/ssh/sshd_config
# Port 22の下に
Port 1022
を追加する

// sshdの再起動
sudo systemctl restart sshd

// firewalldからSSHを削除
sudo firewall-cmd --permanent --remove-service=ssh

// ssh.xmlをコピー
sudo cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/ssh-1022.xml

// ssh-1022.xmlの編集
sudo vi /etc/firewalld/services/ssh-1022.xml
※port="22"をport="1022"に変更する

// firewalldにssh-1022を追加する
sudo firewall-cmd --permanent --add-service=ssh-1022

// firewallの再起動
sudo firewall-cmd --reload

// 状態を確認
sudo firewall-cmd --list-all

// firewalldにhttp/httpsを追加する
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https

// firewallの再起動
sudo firewall-cmd --reload

// 状態を確認
sudo firewall-cmd --list-all

6. SFTPの設定(WinSCP)

7. git/rbenv/Ruby/Railsのインストール

// gitインストール
sudo yum install git
git --version

// rbenv
git clone https://github.com/rbenv/rbenv.git ~/.rbenv

echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc

source ~/.bashrc

git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build

rbenv -v

sudo yum -y install autoconf bison 

sudo yum -y install bzip2 gcc openssl-devel readline-devel zlib-devel

// ruby
rbenv install 2.5.1

rbenv global 2.5.1

ruby -v

which ruby

// RubyGems
gem update --system

gem -v

gem list

// Bundler
gem install bundler

// Rails
gem install rails -v 5.2.1

rails -v

// Node.js
curl -sL https://rpm.nodesource.com/setup_10.x | sudo bash -
sudo yum install nodejs

node -v

8. PostgreSQLのインストール

// PostgreSQL
sudo yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
sudo yum -y install postgresql11-server

psql -V

// データベースクラスタの作成 (UTF8/ロケールなし) 
// 詳細:https://qiita.com/tom-sato/items/e1903cb974fb6c6d5664
sudo PGSETUP_INITDB_OPTIONS="-E UTF8 --locale=C" /usr/pgsql-11/bin/postgresql-11-setup initdb

// データベースサーバの起動
sudo systemctl start postgresql-11.service

// ユーザーを作成する ※ユーザー名はCentOSの一般ユーザー名と同名。
sudo su postgres -c 'createuser -s ユーザー名'

// 動作確認、qで終了
psql postgres
  
// OS起動時にPostgreSQLが起動されるようにする
sudo systemctl enable postgresql-11.service

// PostgreSQLの開発パッケージ
sudo yum install postgresql-devel

[PostgreSQLのコマンド]

\lデータベースの一覧
\cデータベースの選択
\dt;テーブル一覧
\dテーブル名 ※テーブルの構造
SELECT * FROM pg_shadow;
ユーザ毎のパスワード有無の確認 ※あればハッシュ化されている

※「\」は「¥」です。

9. Nginxのインストール

// Nginx
sudo yum install -y nginx
// バージョン
nginx -v

// Nginxの起動
sudo nginx
// Nginxの停止
sudo nginx -s stop

10. Railsプロジェクトの作成

// Railsプロジェクト
cd ~/
mkdir myapp
cd myapp
rails new . -d postgresql

※/home/ユーザー名/myappにプロジェクトが生成される

// データベースの生成
bin/rails db:create

// モデルの作成(モデル/マイグレーションファイルの生成)
bin/rails g model Task name:string description:text

// マイグレーションの実行(テーブルの生成)
bin/rails db:migrate

// コントローラーの作成(コントローラー/ビューの生成)
bin/rails g controller tasks index show new edit

// Gemfileファイルの編集
vi /home/ユーザー名/myapp/Gemfile
※/home/ユーザー名/myapp/Gemfileの末尾を次のようにする

#gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
gem 'unicorn'

// Gemfileファイルを元に各Gemをインストール
bundle

11. unicorn.rbを作成する

/home/ユーザー名/myapp/config/unicorn.rbを作成する

vi /home/ユーザー名/myapp/config/unicorn.rb

[unicorn.rb]

worker_processes Integer(ENV["WEB_CONCURRENCY"] || 4)
timeout 15
preload_app true

listen '/home/ユーザー名/myapp/tmp/unicorn.sock'
pid    '/home/ユーザー名/myapp/tmp/unicorn.pid'

before_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
    Process.kill 'QUIT', Process.pid
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection
end

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

12. Unicornの起動/停止スクリプトを作成する

これはCentOS6以下用です、CentOS7以上は飛ばしてください。

cd /home/ユーザー名/myapp
rails g task unicorn

13. /home/ユーザー名/myapp/lib/tasks/unicorn.rakeを編集する

これはCentOS6以下用です、CentOS7以上は飛ばしてください。

[unicorn.rake]

namespace :unicorn do

  # Tasks
  desc "Start unicorn"
  task(:start) {
    config = Rails.root.join('config', 'unicorn.rb')
    sh "unicorn -c #{config} -E development -D"
  }

  desc "Stop unicorn"
  task(:stop) {
    unicorn_signal :QUIT
  }

  desc "Restart unicorn with USR2"
  task(:restart) {
    unicorn_signal :USR2
  }

  desc "Increment number of worker processes"
  task(:increment) {
    unicorn_signal :TTIN
  }

  desc "Decrement number of worker processes"
  task(:decrement) {
    unicorn_signal :TTOU
  }

  desc "Unicorn pstree (depends on pstree command)"
  task(:pstree) do
    sh "pstree '#{unicorn_pid}'"
  end

  # Helpers
  def unicorn_signal signal
    Process.kill signal, unicorn_pid
  end

  def unicorn_pid
    begin
      File.read("/home/ユーザー名/myapp/tmp/unicorn.pid").to_i
    rescue Errno::ENOENT
      raise "Unicorn does not seem to be running"
    end
  end
end

「development」は最終的リリース(デプロイ)では「production」に変更してください。

※モデル(Task)/コントローラー(tasks)の名称は無関係です。

14. /home/ユーザー名/myapp/publicにindex.htmlを作成する

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello!</title>
</head>
<body> 
  index.htmlが表示されました。<br>
  <br>
  <a href="./tasks/index">Tasks#index</a>
</body>
</html>

15. Nginxの設定ファイル(nginx.conf)の編集

最初にnginx.confをローカルなどにバックアップして下さい。

sudo vi /etc/nginx/nginx.conf

[nginx.conf]

user ユーザー名;

worker_processes auto;

events {
    worker_connections  1024;
}

http {
    server_tokens off;
    
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    access_log  /var/log/nginx/access.log;
    error_log   /var/log/nginx/error.log;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

※/*.confからコメントの緑色になっていますが、全て必要です。

Nginxのバージョンが1.12より新しい場合は「/etc/nginx/conf.d/default.conf」が存在する場合があります。その場合は正常に動作しないので「sudo rm /etc/nginx/conf.d/default.conf」でdefault.confを削除して下さい。

16. myapp.confを作成する

sudo vi /etc/nginx/conf.d/myapp.conf

[myapp.conf]

upstream unicorn {
    server  unix:/home/ユーザー名/myapp/tmp/unicorn.sock;
}

server {
    listen       80;
    server_name  サーバーのIPアドレス;

    root /home/ユーザー名/myapp/public;

    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 X-Forwarded-Proto $scheme;
        proxy_set_header Host $http_host;
        proxy_pass http://unicorn;
    }
}

17. Nginx、Unicornを手動で起動/停止

// Nginxの停止
sudo nginx -s stop
// Nginxの起動
sudo nginx

// ユニコーンの起動確認
ps -ef | grep unicorn | grep -v grep

// これ以下はCentOS6以下が対象です。CentOS7以上は19章を参照。

// ユニコーンの起動 
cd /home/ユーザー名/myapp
bundle exec rake unicorn:start
※エラーが表示されて起動しない場合は、myapp/log/unicorn.logを確認する

// ユニコーンの停止
cd /home/ユーザー名/myapp
bundle exec rake unicorn:stop

ココで次のURLでアクセスできるはずです。

http://IPアドレス/
http://IPアドレス/tasks/index

18. Nginxの自動起動

// 自動起動の設定
sudo systemctl enable nginx

// 設定後にNginxを操作する場合は、次のコマンドで開始、停止、リスタート
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx

// うまく行かない場合は、最初に次のコマンドで停止してから行う
sudo nginx -s stop

19. Unicornの自動起動

サービスファイルの作成と自動起動設定です。

CentOS7以上用 (systemctl)

unicorn_sample_app.serviceのファイルを作成する。

sudo vi /usr/lib/systemd/system/unicorn_sample_app.service

[unicorn_sample_app.service]

[Unit]
Description=Rails sample app service.
After=network.target

[Service]
# ユーザー名
User=ユーザー名

# 環境
Environment=RAILS_ENV=production

# プロジェクトパス
WorkingDirectory=/home/ユーザー名/myapp

# PID
PIDFile=/home/ユーザー名/myapp/tmp/unicorn.pid

# 実行
ExecStart=/home/ユーザー名/.rbenv/shims/bundle exec unicorn -c /home/ユーザー名/myapp/config/unicorn.rb

# 落ちた場合は自動で再起動 ※systemctl stopは除く
Restart=always

[Install]
WantedBy=multi-user.target

ExecStartの「/home/ユーザー名/.rbenv/shims/bundle」のパスは「which bundle」のコマンドで表示されるパスを設定します

// デーモンリロード
sudo systemctl daemon-reload

// 自動起動の設定(On)
sudo systemctl enable unicorn_sample_app

// 自動起動の設定(Off)
sudo systemctl disable unicorn_sample_app

// サービスの開始
sudo systemctl start unicorn_sample_app

// サービスの停止
sudo systemctl stop unicorn_sample_app

// サービスの状態
sudo systemctl status unicorn_sample_app

// サービスのリスタート
sudo systemctl restart unicorn_sample_app

// サービスの一覧情報
sudo systemctl list-unit-files

CentOS6以下用 (chkconfig)

unicornのファイルを作成する。

sudo vi /etc/init.d/unicorn

[unicorn]

#!/bin/bash

#chkconfig:2345 85 70
#description:unicorn shell

USER='ユーザー名'
RAILS_ROOT='/home/ユーザー名/myapp'
NAME='Unicorn'
PID="${RAILS_ROOT}/tmp/unicorn.pid"

start()
{
  if [ -e $PID ]; then
    PID_NUM=`cat ${PID}`
    PROCESS=`ps ho pid p ${PID_NUM} > /dev/null; echo $?`
    if [ "${PROCESS}" != 0 ]; then
      echo 'rm ghost pid'
      rm -f ${PID}
    else
      echo "$NAME already started"
      exit 1
    fi
  fi
  echo "start $NAME"
  su - $USER -lc "cd ${RAILS_ROOT} && bundle exec rake unicorn:start"
}

stop()
{
  if [ ! -e $PID ]; then
    echo "$NAME not started"
    exit 1
  fi
  echo "stop $NAME"
  su - $USER -lc "cd ${RAILS_ROOT} && bundle exec rake unicorn:stop"
}

force_stop()
{
  if [ ! -e $PID ]; then
    echo "$NAME not started"
    exit 1
  fi
  echo "stop $NAME"
  kill -INT `cat ${PID}`

}

reload()
{
  if [ ! -e $PID ]; then
    echo "$NAME not started"
    start
    exit 0
  fi
  echo "reload $NAME"
  #kill -HUP `cat ${PID}`
  su - $USER -lc "cd ${RAILS_ROOT} && bundle exec rake unicorn:reload"
}

restart()
{
    stop
    sleep 3
    start
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  force-stop)
    force_stop
    ;;
  reload)
    reload
    ;;
  restart)
    restart
    ;;
  *)
    echo "Syntax Error: release [start|stop|force-stop|reload|restart]"
    ;;
esac

// パーミッションの変更
sudo chmod 755 /etc/init.d/unicorn

// サービスの自動起動設定
sudo chkconfig unicorn on

// サービスの設定リスト
chkconfig --list

20. 自動起動の確認

OSを再起動してサービスが自動起動されるか確認する。

sudo reboot

21. イメージの保存

ConoHaでは今回作成したイメージを丸ごと保存可能です。保存したイメージから新規にVPSサーバを作成することも可能です。詳細は公式サイトで確認してください。

イメージを再利用すると、/etc/ssh/sshd_configの「PermitRootLogin」(rootログイン禁止設定)「PasswordAuthentication 」(パスワードログイン禁止設定)はデフォルト値に初期化されますので、viで再度変更してください。後は同じ設定のままだと思います

プログラムの流れ

Nginx -> Unicorn -> Rails -> Unicorn -> Nginx

アプリケーションサーバー

UnicornをPumaに変更する場合はNginx + Pumaで複数のRailsプロジェクトを実行するを参考にして下さい。

最後に

長時間、お疲れさまでした。

Nginx、Railsのセキュリティ強化などは各自で検索して対応して下さい。

参考書

現場で使える Ruby on Rails 5速習実践ガイド





関連記事



公開日:2019年09月15日 最終更新日:2019年12月12日
記事NO:02766