Nginx + UnicornなEC2にRailsアプリケーションをCapistranoでデプロイしてみる
はじめに
こんにちは。へっぽこエンジニアのkurashitaです。
今回はAWS上のEC2インスタンスにNginxとUnicornをインストールしてRailsアプリケーションをCapistrano でデプロイした時の手順メモです。
なお各用語についてはおググりください。
サーバはAWSのEC2を用意してある前提です。
以下の一連の記事が非常に参考になりました。
http://qiita.com/hiroshik1985/items/6433d5de97ac55fedfde
EC2上でのインストール作業
今回はstaging環境として構築します。
EC2に ec2-user で ssh ログインします。
git
gitをインストールします。
sudo yum install git
各パッケージ
各パッケージをインストールします。
sudo yum install gcc-c++ glibc-headers openssl-devel readline libyaml-devel readline-devel zlib zlib-devel libffi-devel libxml2-devel libxslt-devel file file-devel mysql-devel ImageMagick ImageMagick-devel # ruby 2.2.0 以降を入れる場合は libffi-develが必要 # nokogiri のインストールに libxml2-devel libxslt-devel が必要 # ruby-filemagic のインストールに file file-devel が必要 # mysql2 のインストールに mysql-devel が必要 # RMagick のインストールに ImageMagick ImageMagick-devel が必要
ruby-build
cd git clone git://github.com/sstephenson/ruby-build.git cd ruby-build sudo ./install.sh
rbenv, ruby
cd git clone git://github.com/sstephenson/rbenv.git ~/.rbenv echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile echo 'eval "$(rbenv init -)"' >> ~/.bash_profile source ~/.bashrc exec $SHELL -l rbenv install -l # 一覧の中から最新か安定版を選ぶ rbenv install 2.2.1;rbenv rehash rbenv global 2.2.1 ruby -v # ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-linux]
bundler
gem install bundler --no-rdoc --no-ri
Nginx
sudo yum install nginx
Nginx設定
/etc/nginx/conf.d/myapp.conf を作成して以下を記述します。
upstream unicorn_server { server unix:/tmp/unicorn.sock fail_timeout=0; } server { listen 80; client_max_body_size 4G; #server_name _; ドメイン未登録 keepalive_timeout 5; root /var/www/myApp/current/public; access_log /var/log/nginx/myApp_access.log; error_log /var/log/nginx/myApp_error.log; 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_server; } location ~ ^/assets/ { root /var/www/myApp/current/public; } error_page 500 502 503 504 /500.html; location = /500.html { root /var/www/myApp/current/public; } }
linked file
gitでは扱わないsecrets.yml
とdatabase.yml
をあらかじめサーバに置いておきます。
var/www/myApp/shared/config/ に secrets.yml と database.yml を作成します。
# secrets.yml staging: secret_key_base: <長い文字列> secret_token: <長い文字列>
文字列は何でも良いのでローカル環境で rake secret などでも作成できます。
# database.yml staging: adapter: mysql2 encoding: utf8 pool: 5 socket: /var/lib/mysql/mysql.sock database: myapp_staging host: myapp_hogehoge_host username: root password: password port: 3306
ディレクトリ所有権の変更
DocumentRootに使う www 以下の所有権を変更しておきます。
chown -R ec2-user www
ローカルでの作業
ここからローカルでの作業になります。
gem インストール
# Gemfile group :production, :staging do gem 'unicorn' end group :development do gem 'capistrano' gem 'capistrano-rails' gem 'capistrano-rbenv' gem 'capistrano-bundler' gem 'capistrano3-unicorn' end
bundle install
Unicorn
設定
config/unicorn/staging.rb に記述します。
# staging.rb root = "/var/www/myApp/current" working_directory root pid "#{root}/tmp/pids/unicorn.pid" stderr_path "#{root}/log/unicorn.log" stdout_path "#{root}/log/unicorn.log" listen "/tmp/unicorn.sock" worker_processes 3 timeout 30 preload_app true before_exec do |server| ENV['BUNDLE_GEMFILE'] = "#{root}/Gemfile" end before_fork do |server, worker| # the following is highly recomended for Rails + "preload_app true" # as there's no need for the master process to hold a connection if defined?(ActiveRecord::Base) ActiveRecord::Base.connection.disconnect! end # Before forking, kill the master process that belongs to the .oldbin PID. # This enables 0 downtime deploys. old_pid = "#{root}/tmp/pids/unicorn.pid.oldbin" if File.exists?(old_pid) && server.pid != old_pid begin Process.kill("QUIT", File.read(old_pid).to_i) rescue Errno::ENOENT, Errno::ESRCH # someone else did our job for us end end end after_fork do |server, worker| # the following is *required* for Rails + "preload_app true", if defined?(ActiveRecord::Base) ActiveRecord::Base.establish_connection end end
Unicornのタスク登録
lib/capistrano/tasks/unicorn.cap を作成します。
# unicorn.cap namespace :unicorn do task :environment do set :unicorn_pid, "#{shared_path}/tmp/pids/unicorn.pid" set :unicorn_config, "#{current_path}/config/unicorn/#{fetch(:rails_env)}.rb" end def start_unicorn within current_path do execute :bundle, :exec, :unicorn, "-c #{fetch(:unicorn_config)} -E #{fetch(:rails_env)} -D" end end def stop_unicorn execute :kill, "-s QUIT $(< #{fetch(:unicorn_pid)})" end def reload_unicorn execute :kill, "-s USR2 $(< #{fetch(:unicorn_pid)})" end def force_stop_unicorn execute :kill, "$(< #{fetch(:unicorn_pid)})" end desc "Start unicorn server" task :start => :environment do on roles(:app) do start_unicorn end end desc "Stop unicorn server gracefully" task :stop => :environment do on roles(:app) do stop_unicorn end end desc "Stop unicorn server immediately" task :force_stop => :environment do on roles(:app) do force_stop_unicorn end end end
capistrano
まずは Cpafile を作ります。
bundle exec cap install
# Capfile require 'capistrano/setup' require 'capistrano/deploy' require 'capistrano/rbenv' set :rbenv_type, :user set :rbenv_ruby, '2.2.1' require 'capistrano/rails' require 'capistrano/rails/assets' require 'capistrano/rails/migrations' require 'capistrano/bundler' require 'capistrano3/unicorn' set :linked_files, %w{config/secrets.yml config/database.yml} Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
デプロイ設定
config/deploy.rb に記述します。
# deploy.rb lock '3.4.0' set :application, 'myApp' set :repo_url, 'git@github.com:lanchester/myApp.git' set :deploy_to, '/var/www/myApp' set :log_level, :debug set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system public/assets} # nokogiri はシステムライブラリを使うため bundle install にオプションを指定する set :bundle_env_variables, { nokogiri_use_system_libraries: 1 } namespace :deploy do desc 'Restart application' task :restart do invoke 'unicorn:restart' end end after 'deploy:publishing', 'deploy:restart'
各環境ごとのデプロイ設定
今回はstaging環境のみ。config/deploy/staging.rb を作成します。
デプロイユーザは本来であれば別に用意するべきなのですが、今回はとりあえずそのまま行きます。
# staging.rb set :stage, :staging set :unicorn_rack_env, "staging" set :branch, 'dev' set :rails_env, 'staging' set :migration_role, 'db' role :app, %w{ec2-user@*.*.*.*} # 実際のサーバのIPアドレスを指定します。 role :web, %w{ec2-user@*.*.*.*} role :db, %w{ec2-user@*.*.*.*} set :ssh_options, { keys: [File.expand_path('~/.ssh/myApp-stg.pem')], forward_agent: true, auth_methods: %w(publickey) } server '*.*.*.*', user: 'ec2-user', roles: %w{web app db}
デプロイ先サーバの設定
GitHubのリポジトリにアクセスするための公開鍵・秘密鍵を生成
cd ~ ssh-keygen -t rsa -C myApp-stg ssh-add ~/.ssh/id_rsa # 上記の鍵をssh-agent に登録します # すでに別の鍵を追加していた場合、デプロイ時にpermission deniedになることがあるので # ssh-add -D 等で登録削除したのち改めて登録
GitHubリポジトリの設定
1) 対象のリポジトリのページへ移動
2) Settingsへ移動
3) Deploy keysへ移動
4) Add Deploy Keysで上記で作成した公開鍵をコピペ
接続確認
初回デプロイ時のみgithubへの接続確認が必要です。
ssh -T git@github.com
デプロイ
unicorn の起動
config/unicorn/staging.rb の設定で unicorn を起動します。
bundle exec unicorn -D -c /var/www/myApp/current/config/unicorn/staging.rb -E staging
以上設定で不備がなければデプロイ可能です。
cap staging deploy
お疲れ様でした。
TAG
基本的にRuby on Railsで開発してます。最近はvue.jsも。好きな塔は円城です。
TAG
- Android
- AWS
- Bitrise
- CodePipeline
- Firebase
- HTML
- iOS
- IoT
- JavaScript
- KPI
- Linux
- Mac
- Memcached
- MGRe
- MGReのゆるガチエンジニアブログ
- MySQL
- PHP
- PICK UP
- PR
- Python
- Ruby
- Ruby on Rails
- SEO
- Swift
- TIPS
- UI/UX
- VirtualBox
- Wantedly
- Windows
- アクセス解析
- イベントレポート
- エンジニアブログ
- ガジェット
- カスタマーサクセス
- サーバ技術
- サービス
- セキュリティ
- セミナー・展示会
- テクノロジー
- デザイン
- プレスリリース
- マーケティング施策
- マネジメント
- ラボ
- リーンスタートアップ
- 企画
- 会社紹介
- 会社紹介資料
- 勉強会
- 実績紹介
- 拡張性
- 採用
- 日常
- 書籍紹介
- 歓迎会
- 社内イベント
- 社員インタビュー
- 社長ブログ
- 視察
- 開発環境