Capistrano 3

Capistrano обновился до третьей версии, multistage из коробки и ощутимый прирост скорости.

Установка #

Добавляем в Gemfile необходимое:

group :development do
  # deploy
  gem 'capistrano-rails', require: false
  gem 'capistrano-bundler', require: false
  gem 'capistrano-rvm', require: false
end

Генерация файлов:

bundle exec cap install

В 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/tree/master/assets
# https://github.com/capistrano/rails/tree/master/migrations
#
require 'capistrano/rvm'
# require 'capistrano/rbenv'
# require 'capistrano/chruby'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'

# 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:

# Application
# ===========
set :application, "neosapien"
set :deploy_to, "/data/projects/#{fetch :application}"
set :rails_env, "production"

set :linked_files, %w{config/database.yml}
set :linked_dirs, %w{log tmp/pids tmp/sockets vendor/bundle public/uploads}

# Git
# ===
set :scm, :git
set :branch, "master"
set :deploy_via, :export
set :repo_url, "git@github.com:ksevelyar/neosapien.git"

# SSH
# ===
set :ssh_options, {
  user: "ksevelyar",
  forward_agent: true
}

# Capistrano
# ==========
set :format, :pretty
set :log_level, :debug
set :keep_releases, 7

# Tasks
# =====
namespace :deploy do
  after :finishing, "deploy:cleanup"

  after :publishing, :restart

  desc 'Start application'
  task :start do
    on roles(:app) do
      execute "sudo /etc/init.d/unicorn_#{fetch :application} start"
    end
  end

  desc 'Stop application'
  task :stop do
    on roles(:app) do
      execute "sudo /etc/init.d/unicorn_#{fetch :application} stop"
    end
  end

  desc 'Restart application'
  task :restart do
    invoke 'deploy:stop'
    sleep 3
    invoke 'deploy:start'
  end
end

Здесь нужно заменить название приложения, пользователя, репозиторий.

После этого можно открыть config/deploy/production.rb и указать настройки специфичные для сервера / окружения:

set :stage, :production
set :rvm_type, :system

server 'example.com', roles: %w{web app db}

Подготовка сервера #

Попробуем задеплоить приложение на сервер:

cap production deploy

Здесь Capistrano будет ныть из-за отсутствия файла database.yml:

ERROR linked file /data/projects/neosapien/shared/config/database.yml does not exist on 192.168.0.1

Заходите на сервер через ssh и создавайте нужный файл:

ssh 192.168.0.1
vim /data/projects/neosapien/shared/config/database.yml

Не забудьте перезапустить nginx и установить в init сервис для unicorn (пример конфигов):

ssh-agent + zsh #

Я использую одну команду для деплоя

alias deploy='ssh_agent && cap production deploy'

ssh-agent() {
  if [[ -z "$SSH_AUTH_SOCK" ]]; then
    pkill ssh-agent
    eval $(ssh-agent)
    ssh-add
  fi
}

Таски #

Так выглядит переписанный таск для синхронизации баз данных:

lib/capistrano/tasks/sync.cap

namespace :sync do
  task :db do
    require 'yaml'

    on roles :db do
      production_db  = YAML::load(capture "cat #{current_path}/config/database.yml")['production']
      dump = "#{production_db['database']}.sql"


      execute "PGPASSWORD='#{production_db['password']}' && export PGPASSWORD && \
               pg_dump -Fc --compress=9 \
               --username=#{production_db['username']} \
               --host localhost \
               --file=#{current_path}/tmp/#{dump} \
               #{production_db['database']} ; \
               unset PGPASSWORD"



      download! "#{current_path}/tmp/#{dump}", "tmp/"
      execute "rm -f #{current_path}/tmp/#{dump}"

      development_db = YAML::load_file('config/database.yml')['development']

      system "pg_restore -Fc \
              --clean \
              --username=#{development_db['username']} \
              --host localhost \
              --dbname=#{development_db['database']} \
              tmp/#{dump}"

      system "rm -f tmp/#{dump}"
    end
  end
end

Добавить комментарий