Rals3.2.13で始めるGit連携Capistrano 2系による自動デプロイ


Eye Catch Image

RailsにCapistranoを導入して、Gitリポジトリと連携した自動デプロイのしくみを構築していきます。一度組み上げてしまえば、その後の作業量が激減するんでオススメです!

ちなみに、localにステージング環境を作る場合には、Capistrano 複数環境へのデプロイ[localhostへのデプロイ]がオススメです。


😎 リモートのGitリポジトリを準備

デプロイ先のサーバがアクセスできるGitリポジトリを準備してください。無制限でプライベートなGitリポジトリを作成できるBitBucketがオススメです!

ちなみに、BitbucketでのSSHキーセットアップ手順はこちらにまとめています

😸 Gitにリモートリポジトリを追加

ローカル側でGitにリモートリポジトリを追加する。

git remote add remote-name url(https://xxxやgit@xxxなど)

👽 本番DBでMySQLを使う場合

デプロイ先のDBの接続用ユーザーとデータベースを作成するために、次のコマンドを実行。

mysql -u root -p
# 新規ユーザーを作成する場合
GRANT ALL PRIVILEGES ON database_name.* TO user_name@localhost IDENTIFIED BY 'user_password';
# 既存のユーザーに権限を追加する場合
GRANT ALL PRIVILEGES ON database_name.* TO user_name@localhost;
CREATE DATABASE database_name;
FLUSH PRIVILEGES;
exit
mysql -u user_name -p
SHOW DATABASES;
> +--------------------------+
> | Database |
> +--------------------------+
> | information_schema |
> | database_name | #<= DBの作成成功
> +--------------------------+
exit

🗻 Gemfileの追加

Gemfileを追加して、bundle installを実行。

group :deployment do
# Capistraono (Deploy支援)
gem 'capistrano'
gem 'capistrano-ext'
gem 'capistrano_colors'
gem 'rvm-capistrano'
end
# メンテナンスモード画面の表示
gem 'turnout'

🏀 Capistranoの設定ファイルを生成

次のコマンドでCapistranoの設定ファイルdeploy.rbらを生成。

capify .
> [add] writing './Capfile'
> [add] writing './config/deploy.rb'
> [done] capified!

🗽 Capistrano deploy.rbの設定

deploy.rbに以下を記入

#### TEST_APPにアプリ名を登録 ####
set :application, "TEST_APP"
# capistranoの出力をカラーに
require 'capistrano_colors'
# cap deploy時に自動で bundle installを実行
require "bundler/capistrano"
set :bundle_flags, "--no-deployment --without test development"
# RVMを利用している場合は必要
require "rvm/capistrano"
#### RVMで利用するRubyのバージョンを設定(1.9.3を変更) ####
set :rvm_ruby_string, '1.9.3'
set :rvm_type, :user
# rvmのパスは環境によって変更してください
set :rvm_path, '/usr/local/rvm'
set :rvm_bin_path, "#{rvm_path}/bin"
set :rvm_lib_path, "#{rvm_path}/lib"
# gitリポジトリの設定
#### git_remote_urlにgitのリモートURLを登録 ####
set :repository, "git_remote_url"
set :scm, :git
set :branch, "master"
set :deploy_via, :remote_cache
#### deploy_folder_path : デプロイ先のフォルダパスを設定 ####
set :deploy_to, "deploy_folder_path"
set :rails_env, "production"
# デプロイ先のサーバの設定
#### サーバのIPとSSHポートを設定 ####
server "IP:SSH_PORT", :app, :web, :db, :primary => true
# SSHユーザの設定
#### ssh_user : sshで接続するユーザー名をセット ####
set :user, 'ssh_user'
#### user_group : コマンドを実行するユーザーグループ名をセット ####
set :user_group, 'user_group'
#### local_ssh_key_path : ssh_keyのパスをセット ####
ssh_options[:keys] = %w(local_ssh_key_path)
ssh_options[:auth_methods] = %w(publickey)
#### sudo_password : deploy 先でのssh_userのsudoパスワード ####
set :password, "sudo_password"
set :use_sudo, true
# リモートでもローカルのssh keyを使えるようにする
ssh_options[:forward_agent] = true
default_run_options[:pty] = true
set :normalize_asset_timestamps, false
# 過去のデプロイしたフォルダを履歴として保持する数
set :keep_releases, 5
# assets:precompile
namespace :assets do
task :precompile, :roles => :web do
run "cd #{current_path} && RAILS_ENV=#{rails_env} bundle exec rake assets:precompile"
end
end
namespace :deploy do
# Passengerの実行ユーザー/Groupをセット
task :set_file_process_owner do
sudo "chown -R #{user}.#{user_group} #{deploy_to}"
end
# 本番サーバでPassenger以外を使っている場合は適宜変更して下さい。
desc "Passenger用に起動/停止タスクを変更"
task :restart, :roles => :web do
run "touch #{current_path}/tmp/restart.txt"
end
end
# deploy ==========================
before :deploy, "deploy:set_file_process_owner"
after :deploy, "maintenance:on"
after :deploy, "deploy:migrate"
after :deploy, "assets:precompile"
after :deploy, "deploy:restart"
after :deploy, "maintenance:off"
after :deploy, "deploy:cleanup" # 古い履歴のフォルダを削除

🐯 メンテナーンス画面の設定

メンテナーンス画面での表示のために、config/maintenance.ymlを追加。
(詳細は、tmedetbekov/turnout · GitHubを参照)

---
reason: Someone told me I should type `sudo rm -rf /`
allowed_paths:
- ^/help
- ^/contact_us
allowed_ips:
- 127.0.0.1
- 192.168.0.0/24

🍮 デプロイ前のチェックリスト

* deploy.rbのパラメータをすべて設定したかチェック
* 本番DBの設定をdatabase.ymlに追加しているか?
* Gitリポジトリのデプロイ用のブランチが最新の状態か?

🎂 デプロイ手順

デプロイに必要なディレクトリを生成して、デプロイを実行。

cap deploy:setup
cap deploy
> .... # <= 色々コマンドを実行
> servers: [server_ip]
> [server_ip:port] executing command
> command finished in XXXms # <= で成功

🎉 Apacheのバーチャルホストを設定

Apacheのバーチャルホストの設定ファイル(sudo vim /etc/http/conf.d/vhost.confなど)をApache VirtualHostの設定を参考に編集。

🚌 補足:Deploy時にSitemapを生成する

sitemapを生成するgem「sitemap_generator」を使っている場合は、Delopy時にSitemapを自動で生成/更新できます。deploy.rbに次の内容を追加。

namespace :deploy do
desc "sitemapの更新"
task :refresh_sitemaps do
run "cd #{latest_release} && RAILS_ENV=#{rails_env} bundle exec rake sitemap:refresh"
end
end
after :deploy, "deploy:refresh_sitemaps"

もしRailsでsitemapを生成してくれるGem「sitemap_generator」に興味があれば、「meta-tagsとsitemap_generatorで始めるRails 3.2のSEO対策」を御覧ください。

🐮 補足:deploy時にseedデータ(seed_fu)を自動で読み込む

もし、seed_fuを使っている場合は、本番デプロイ時にseedデータを本番DBに読み込ませることも簡単です。config/deploy.rbに以下を追加。

namespace :deploy do
desc "Load the seed data from db/seeds.rb"
task :seed do
run "cd #{current_path} && RAILS_ENV=#{rails_env} bundle exec rake db:seed_fu"
end
end
after :deploy, "deploy:seed"

もしseedファイルの効率的な管理ができるgem seed_fuに興味があれば、「seed-fuで始める効率的なRails Seed管理」を御覧ください。

🤔 補足: yaml_dbでダンプしたデータをロードする処理を組み込

DBをダンプしたデータの取り込みをデプロイプロセスに追加したい場合はconfig/deploy.rbに以下を追加。

namespace :deploy do # namespaceは任意
desc "Load the seed data from db/data.yml"
task :dump_yml_load do
run "cd #{current_path} && RAILS_ENV=#{rails_env} bundle exec rake db:load"
end
end
after :deploy, "deploy:dump_yml_load"

もし、RakeコマンドでDBのダンプロードができるyaml_dbについて興味がある方は、「yaml_db RailsのDBをコマンド一つでYAML形式でダンプ/ロードできるRubyGem」をご覧になってみてください。

😀 補足:crontabを簡単に管理できるwheneverとの連携

wheneverはcrontabを簡単に管理できるツールです。もしwheneverを使っている場合は、設定方法は下の内容をconfig/deploy.rbに記述するだけです。

# whenever
set :whenever_command, "bundle exec whenever"
set :whenever_environment, defer { rails_env }
#### SERVER_IPとSSH_PORTをセット ####
set :whenever_roles, defer { "SERVER_IP:SSH_PORT" }
require "whenever/capistrano"

あとはcap deployのたびにcrontabをアプデートしてくれます。

もし、crontabのRubyGem製管理ツールwheneverに興味があれば、「Whenever 導入が超簡単なcorntab管理ライブラリRubyGem[Rails]」をご一読ください。

🎳 補足 : Capistrano(cap)命令集

cap deploy:setup # デプロイ先に必要なディレクトリを作成 初回のみ実行
cap deploy # デプロイ先でgit cloneなど
cap deploy:update_code #コードをアップデートしてくれる

🐞 エラー1: MySQL.h is missing.

MySQL.h is missing...と出る場合は以下をサーバ側で実行。

sudo yum --enablerepo=remi --disablerepo=base,updates install mysql-devel

🏈 エラー2: libxml2 is missing.

libxml2 is missing....と出る場合は以下をサーバ側で実行。

yum install -y libxml2 libxml2-devel libxslt libxslt-devel

🐡 参考リンク

Deploying with Capistrano

RVM: Ruby Version Manager - RVM with Capistrano

[開発環境] さくらVPS Capistrano編

花見の季節にさくらVPS: Nginx+Unicorn+Rails+Capistrano

bitbucket+Capistrano(+multistage)でデプロイ設定

仕事帳: Webクローラフレームワーク Anemone の紹介

mysql - Errors Installing mysql2 gem via the Bundler - Stack Overflow

cohakim’s blog » Railsアプリの管理がちょっとだけ楽になるCapistranoレシピ3つ

🍣 検証環境

今回の記事の検証環境は以下のとおりです。

Local/Server:
  Ruby: 1.9.3
  Rails: 3.2.13

Local:
  OS: Mac Lion(macOS 10.7)
  Server App: Pow
  MySQL: 5.6.10

Server(さくらVPS 2Gプラン):
  CentOS: centos-release-6-2.el6.centos.7.x86_64
  Server app: Apache/2.2.15 (UNIX)
  MySQL: 5.5.22

😼 変更来歴

12/15 08:45 Capistrano-rvmの設定項目を追加、エラー対策を追加

12/18 14:15「補足:deploy時にseedデータ(seed_fu)を自動で読み込む」を追加

12/20 21:00「補足: yaml_dbでダンプしたデータをロードする処理を組み込」を追加

12/21 17:40「補足:Deploy時にSitemapを生成する」を追加

12/24 11:05全体の記述を修正(特にフォルダ所有権関連)

12/24 17:00「補足:wheneverとの連携」を追加

12/24 17:20 rvmのgemsetの指定についての記述を追加

12/25 09:30 rvmのgemsetに関する記述を削除、構成を変更

01/05 10:30 assets/precompileを変更時のみ実行するように修正

02/12 17:40 capistrano_rsync_with_remote_cacheを取り外し

04/22 18:30 Gem turnoutを追加、全体的に最新の状態にアップデート

📚 おすすめの書籍