node(expressjs)なアプリを作って、capistrano2でデプロイしていたのだけど、capistrano3が登場してずいぶんスマートになったとのことで、capistrano3に載せ替えてみた、という話です。
capistranoって何?
失礼なほどざっくり言ってしまえば、capistranoはrubyで書かれたデプロイツールで、gitやsvnなどのリポジトリからモジュールを取得、デプロイ先のしかるべきディレクトリに配置し、dbの変更、assetsの生成、プロセスの再起動なんかを自動でやってくれるすぐれものです。
capistrano2っていうのが長く広く使われていたところに、capistrano3が登場していろいろとスマートになったようです。
capistrano + node
nodeなアプリを対象とするにあたり、リモート(デプロイ先)でのnodeのパスを正しく設定したり、npmでライブラリ群をインストールしたり、っていうところをどうやるのか、というのが肝になるのかなぁ、と思っていたら、
っていうのが既にあったので、使わせて頂きました。
capistrano-nvm
capistrano上で動作するnvmタスクを提供してくれる。
ローカルなnvmにも、システムワイドなnvmにも対応している。僕のサーバはnvmをシステムワイドで入れているので助かった。([node] nvmをシステムワイドに適用する。)
capistrano-npm
capistrano上で動作するnpmタスクを提供してくれる。
Railsアプリのデプロイプロセスでbundle installを実行するように、npm installを走らせる。
もともとcapistrano-npmだけ追加してやったらnpmのパス(、つまりnode関連のパス)が解決できずどうしたものか、とはまっていたところに、capistrano-nvmと併せて使ったらば解決できたので、セットで使うのがいいのかと。
deploy
実際にデプロイするには、
- リモートホスト(デプロイ先ホスト)の環境設定
- capistranoのインストール
- capistrano-nvmのインストール
- capistrano-npmのインストール
- Capfile, deploy.rbの作成
- deploy
という流れになりますね。
リモートホスト(デプロイ先ホスト)の環境設定
リモートで作業するユーザとSSHの設定が基本になります。
ユーザ作って、ディレクトリ掘って、SSHでフォワードできれば良さそう。
capistranoの本家サイトにある、Authentication & Authorisationのページのとおりにやりました。
capistrano,capistrano-nvm,capistrano-npmのインストール
gemコマンドでも、bundle経由でもいいと思います。今回はgemコマンド叩いてインストールしてしまいました。
$ gem install capistrano
$ gem install capistrano-nvm
$ gem install capistrano-npm
Capfile, deploy.rbの作成
ここがcapistrano2から変わったところの1つで、2の頃はcapifyっていうコマンドがあって、一番最初にcapifyしていたのが、
cap installに変わりました。
cap install すると、Capfileとdeploy.rbとかstaging.rbとかproduction.rbが作られます。環境別の設定ファイルのひな形が生成されます。いわゆるマルチステージに対応しています。stagingっていうのは、順productionというのか、本番の手前っていう位置づけの環境と考えるといいと思います。
Capfileではそのプロジェクトにおけるcapistranoの環境を書きます。
deploy.rbとdeploy/*.rbには、デプロイに関する詳細やタスクを書きます。
自作でタスクを作る場合は、lib/capistrano/tasksに拡張子.capを作ります。
今回は、カスタムタスクはなしで、Capfile、deploy.rb、production.rbだけ弄って、それぞれ次のように書きました。
# Capfile
# Load DSL and Setup Up Stages
require 'capistrano/setup'
# Includes default deployment tasks
require 'capistrano/deploy'
# Includes tasks from other gems included in your Gemfile
#
# For documentation on these, see for example:
#
# https://github.com/capistrano/rvm
# https://github.com/capistrano/rbenv
# https://github.com/capistrano/chruby
# https://github.com/capistrano/bundler
# https://github.com/capistrano/rails
#
# require 'capistrano/rvm'
# require 'capistrano/rbenv'
# require 'capistrano/chruby'
# require 'capistrano/bundler'
# require 'capistrano/rails/assets'
# require 'capistrano/rails/migrations'
require 'capistrano/nvm' # <= 追加
require 'capistrano/npm' # <= 追加
# Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r }
# config/deploy.rb
# config valid only for Capistrano 3.1
lock '3.1.0'
set :application, 'application_name'
set :repo_url, 'ssh://hostname.your.repo/path/to/your_repo.git'
# Default branch is :master
# ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }
# Default deploy_to directory is /var/www/my_app
# set :deploy_to, '/var/www/my_app'
set :deploy_to, '/var/www/application_name'
# Default value for :scm is :git
# set :scm, :git
# Default value for :format is :pretty
# set :format, :pretty
# Default value for :log_level is :debug
# set :log_level, :debug
# Default value for :pty is false
# set :pty, true
# Default value for :linked_files is []
# set :linked_files, %w{config/database.yml}
# Default value for linked_dirs is []
# set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}
set :linked_dirs, %w{log node_modules}
# Default value for default_env is {}
# set :default_env, { path: "/opt/ruby/bin:$PATH" }
# Default value for keep_releases is 5
# set :keep_releases, 5
set :nvm_type, :system
set :nvm_node, 'v0.10.26'
set :nvm_map_bins, %w{node npm}
namespace :deploy do
desc 'Restart application'
task :restart do
on roles(:app), in: :sequence, wait: 5 do
# Your restart mechanism here, for example:
# execute :touch, release_path.join('tmp/restart.txt')
execute :sudo, :restart, 'name_of_upstart_script'
end
end
after :publishing, :restart
after :restart, :clear_cache do
on roles(:web), in: :groups, limit: 3, wait: 10 do
# Here we can do anything such as:
# within release_path do
# execute :rake, 'cache:clear'
# end
end
end
end
deploy
ここまで準備ができたところで、デプロイします。
capistrano2の頃のように、cap deploy:setupとかはもう要らない。いきなり、
cap deployでよい。
$ cap production deploy