LoginSignup
31
32

More than 5 years have passed since last update.

Capistranoでのrsyncを利用したアプリケーションのデプロイ

Last updated at Posted at 2014-06-10

Capistrano 3系でちょうどマッチした利用方法が見つからなかったので、試行錯誤した結果をまとめた。

Capistranoでのrsyncを利用したRubyアプリケーションのデプロイ

使用するライブラリ

  • capistrano(3系)
  • bundler
  • capistrano-rsync
  • capistrano-bundler

デプロイのフローについて

リポジトリがアプリケーションが動作するサーバーのネットワークからアクセスできないという事情があったので、事前に依存ライブラリを取得した上で、リリースできるように、下記のようなデプロイのフローにした。
イメージとしては、JavaでWARとかにパッケージングしたのを配布する感じ。

  1. デプロイサーバー上で、リポジトリからソースの取得
  2. デプロイサーバー上で、あらかじめ取得したソースが依存しているライブラリを取得
  3. 実行サーバーに対して、リソースの展開
  4. 実行サーバーでのライブラリのインストール

デプロイサーバーへのコピー処理

Capistrano3系では、capistrano-rsyncというgemが、ちょうど上記の動作フローとマッチした実行ステップをもっていたので、このライブラリを使用することにした。

大雑把なステップは下のような感じ。

  1. リポジトリからソースの取得 (rsync:stage)
  2. 実行サーバーへのリソースのコピー (rsync:release)

依存ライブラリの取得処理

依存ライブラリの取得に、bundle package --allを利用する。こうすることで、あらかじめ、vendor/cacheに、依存しているライブラリがダウンロードされる。

実行するステップについては、リポジトリからソースの取得のタイミングで行うことで、実行サーバーへコピーする時にvendor/cacheも含めて、コピーされるようにする。

また、platformに依存して、インストールするgemが変わるようなもの(libv8とか)については、デプロイ作業を行うサーバーのplatformと実行サーバーのplatformが異なると、インストールが失敗するので、事前に、gem fetch等で取得しておく。

namespace :package do
  desc 'packaging gems'
  task :gems do
    run_locally do
      Dir.chdir 'tmp/deploy' do
        # bundlerでの環境変数を引き継がない状態で、実行
        Bundler.with_clean_env do
          system 'BUNDLE_GEMFILE=Gemfile bundle package --all --quiet'
          # 環境(platform)に依存しているライブラリがあれば別途、取得
        end
      end
    end
  end
end

after 'rsync:stage', 'package:gems'

rsync処理での設定

namespace :rsync do
  # 3.2系から、scmのset_current_revisionが呼ばれるようになったことに対応
  # cf. https://github.com/moll/capistrano-rsync/issues/15
  # internally needed by capistrano's "deploy.rake"
  task :set_current_revision do
    run_locally do
      within fetch(:rsync_stage) do
        rev = capture(:git, 'rev-parse', 'HEAD')
        set :current_revision, rev
      end
    end
  end

  # rsyncのコマンドオプションを指定
  task :set_options do
    set :rsync_options, %w(-az --delete --delete-excluded --exclude .git*)
  end

end

before 'rsync', 'rsync:set_options'

デプロイ処理での設定

rsyncを使う設定と、取得したパッケージを利用するように、bundlerのオプションを追加する。

set :repo_url, '<gitリポジトリのURL>'
# :gitの代わりに、:rsyncを指定
set :scm, :rsync

## Bundler
set :bundle_path, -> { shared_path.join('bundle') }
set :bundle_without, %w(development test).join(' ')
# --localオプションを指定することで、vendor/cache経由でインストール
set :bundle_flags, '--deployment --local'

パッケージングしたライブラリの取り回しの修正

上記の設定だと、毎回のリリースごとに、bundlrがパッケージングしたvendor/cacheが丸ごとコピーされてしまい、ディスクスペース的に無駄なので、deploy.rb:linked_dirに、vendor/cacheを追加した上で、シンボリックリンクをはるようにします。

# deploy.rbでのシンボリックリンクの対象にvendor/cacheを追加
set :linked_dirs, %w(log tmp/pids tmp/cache tmp/sockets vendor/bundle vendor/cache)

上記で作成したシンボリックリンクのリンク先を書き換えて、rsyncしているディレクトリのvendor/cacheを指すようにします。

namespace :release do
  desc 'symlink cache dir'
  task :symlink_cache do
    on roles(:app) do
      within release_path do
        execute "cd '#{release_path}'; ln -sfn #{fetch(:deploy_to)}/#{fetch(:shared_path)}#{fetch(:rsync_cache)}/vendor/cache vendor/cache"
      end
    end
  end
end

after 'deploy:symlink:linked_dirs', 'release:symlink_cache'
31
32
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
32