2013/08/15

node(express.js)なアプリをcapistranoでdeployする。

Railsアプリをサーバーにデプロイする際に、Capistranoを使ってきたけど、これをNode.js+express.jsなアプリでも使えればなぁ、と思っていて、@d_akatsukaさんの、
Node.js アプリをデプロイして Upstart で起動させる Capistrano レシピを書いた
を大いに参考にさせて頂いて、やっと自分の環境でも動かすことができたので、まとめてみる。

Capistrano

Capistranoは、rubygemsとしてインストールする。

  $ gem install capistrano
  $ cap --version
  Capistrano v2.15.4
ちなみに、僕の環境のrubyはrbenv+ruby_buildでインストールしたruby2.0.0p0。

Capfileとdeploy.rb

Capistranoでデプロするには、一般的に、Capfileとdeploy.rbという2つのRubyスクリプトが必要になる。 今回は、express.jsアプリケーションの標準的なディレクトリ構成にこの2つのファイルを追加した。

project_root
├── Capfile
├── app.js
├── config
│   └── deploy.rb
├── node_modules
├── package.json
├── public
├── routes
└── views

それぞれ、次のような内容を書く。
#
# Capfile
#
load 'deploy'
# Uncomment if you are using Rails' asset pipeline
    # load 'deploy/assets'
load 'config/deploy' # remove this line to skip loading any of the default tasks
#
# deploy.rb
#
set :application,        'application_name'
set :host,               'your.host.com' # or ip address.
set :user,               'username'
set :password,           'password'
set :deploy_to,          "/var/www/apps/#{application}"
set :shared_children,    %w(log node_modules)

set :node_file,          'app.js'
set :node_version,       "v0.10.12"
set :application_binary, "/usr/local/nvm/#{node_version}/bin/node"
set :npm_binary,         "/usr/local/nvm/#{node_version}/bin/npm"

set :scm,          :git
set :repository,   'git://git.host/your/repository.git'
set :branch,       'master'
set :deploy_via,   :remote_cache

role :app,           host
set  :use_sudo,      false
set  :default_run_options, :pty => true

namespace :deploy do

  task :default do
    update
    start
  end

  task :cold do
    update
    start
  end

  task :setup, :expect => { :no_release => true } do
    dirs = [deploy_to, release_path, shared_path]
    dirs += shared_children.map { |d| File.join(shared_path, d) }
    run "mkdir -p #{dirs.join(' ')}"
    run "chmod g+w #{dirs.join(' ')}" if fetch(:group_writable, true)
  end

  task :finalize_update, :expect => { :no_release => true } do
    run "chmod -R g+x #{latest_release}" if fetch(:group_writable, true)
    run <<-CMD
      rm -rf #{latest_release}/log #{latest_release}/node_modules &&
      ln -s #{shared_path}/log #{latest_release}/log &&
      ln -s #{shared_path}/node_modules #{latest_release}/node_modules
    CMD
  end

  task :start, :roles => :app do
    run "#{sudo} restart #{application} || #{sudo} start #{application}"
  end

  task :stop, :roles => :app do
    run "#{sudo} stop #{application}"
  end

  task :restart, :roles => :app do
    start
  end

  task :npm, :roles => :app do
    run "cd #{latest_release} && #{npm_binary} install"
  end

  desc "writes the upstart script for running the daemon."
  task :write_upstart_script, :roles => :app do
    upstart_script = <<-UPSTART
description "#{application} upstart script"

start on (local-filesystem and net-device-up)
stop  on shutdown

respawn
respawn limit 5 60

script
  chdir #{current_path}
  exec sudo -u #{user} NODE_ENV="production" #{npm_binary} start >> log/production.log 2>&1
end script
    UPSTART

    put upstart_script, "/tmp/#{application}.conf"
    run "#{sudo} mv /tmp/#{application}.conf /etc/init"
  end

end

after 'deploy:setup',           'deploy:write_upstart_script'
after 'deploy:finalize_update', 'deploy:npm'
ほぼ、前述の@d_akatsukaさんの記事のdeploy.rbとかわらないけど、サーバーサイドでnvmをシステムワイドに適用していることで、 nvm経由のnodeやnpmの起動で、パスの指定がこのようになった。

デプロイする

初めてサーバーにデプロイする場合は、

 $ cap deploy:setup
を実行する。コレが成功すると、:deploy_toで指定したディレクトリがサーバーサイドで生成され、 さらに/etc/init配下にupstartのスクリプトが生成される。
通常は、
 $ cap deploy
を実行すると、リポジトリから最新モジュールを取得し、転送、配置、upstartでnodeの再起動をやってくれる。
上述のdeploy.rbで、
 $ cap deploy:start
 $ cap deploy:stop
 $ cap deploy:restart
 $ cap deploy:rollback
を試したけど、うまく動いた。

0 件のコメント: