jueves, 6 de marzo de 2014

Despliegue de aplicaciones Rails con Capistrano v3

Como decía en el anterior post sobre la configuración de una aplicación rails con Nginx y Unicorn, ahora comentaré cómo he realizado el despliegue usando Capistrano 3. Realmente es una herramiente muy sencilla, que permite incluir muchas opciones de configuración, aunque lo básico ya viene prácticamente hecho de serie.

Para empezar, incluimos en el Gemfile las gemas que vamos a usar:


# Deploy with Capistrano
gem 'capistrano'
gem 'capistrano-rails'
gem 'capistrano-rvm'
# integrate bundler with capistrano
gem 'capistrano-bundler'

Ejecutamos bundle install y una vez que hemos instalado las gemas, creamos la estructura de ficheros que necesita Capistrano. Para ello simplemente habrá que ejecutar: cap install.
A partir de aquí, simplemente tendremos que configurar los ficheros generados de acuerdo a las necesidades de nuestro servidor.





En primer lugar modificaremos el fichero Capfile. Incluimos las gemas necesarias, en función de las funcionalidades y la arquitectura de nuestra aplicación. Yo usaba RVM como gestor de versiones de Ruby, Assets por ser versión 3.2 de rails y Sidekiq para trabajos asíncronos. Y estos son las librarías incluidas:

require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rvm'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require "sidekiq/capistrano"

Posteriormente definimos en el deploy.rb  las tareas que podrá ejecutar Capistrano. Aquí irá la ejecución de Unicorn y cualquier otro proceso que precisemos. Al haber incluido ya la librería sidekiq/capistrano no es necesario definir aquí la tarea para levantar Sidekiq. Se levantará automáticamente al realizar el Deploy. Las tareas para Unicorn son:


  desc "Start unicorn"
  task :start do
    on roles(:app), in: :sequence, wait: 5 do
      within current_path do
        with rails_env: fetch(:stage) do
          execute :bundle, "exec unicorn_rails -c config/unicorn.rb -D"
        end
      end
    end
  end

  desc "Stop unicorn"
  task :stop do
    on roles(:app), in: :sequence, wait: 5 do
      execute "kill -s QUIT `cat #{shared_path}/../tmp/pids/unicorn.pid`" if test("[ -f #{shared_path}/../tmp/pids/unicorn.pid ]")
    end
  end
  desc 'Restart unicorn'
  task :restart do
    on roles(:app), in: :sequence, wait: 5 do
      # this is a bad way to invoking, but spent 3 hrs searching for this
      Rake::Task["deploy:stop"].invoke
      Rake::Task["deploy:start"].invoke
    end
  end

Aquí también debemos configurar el nombre de la aplicación y el tipo de control de versiones que usamos. Por defecto es GIT, y la URL será la de nuestro repositorio remoto (Github, Bitbucket, ...).

El siguiente fichero que debemos configurar será el production.rb. Aquí debemos incluir las propiedades del servidor (o servidores) en el que vamos a realizar los despliegues.

En el caso de usar una instancia EC2 de Amazon AWS, habrá que tener algún aspecto en cuenta para que no fallen las conexiones.
En primer lugar, la dirección del servidor será la de la Elastic IP que hayamos configurado para nuestra instancia. Además, deberemos tener incluida la clave pública de nuestra máquina en la instancia. es decir, que podamos hacer un SSH sin tener que introducir usuario/password. También se podría hacer usando el fichero clave/valor que nos facilita AWS, pero es más sencillo de este modo.
Finalmente, tendremos que incluir la clave pública de nuestra instancia en el repositorio remoto, para que pueda hacer pull del proyecto sin introducir la contraseña.

Si hemos realizado correctamente la configuración, los comandos para hacer el despliegue serán:

cap production deploy
cap production deploy:start

Y tendremos nuestro servidor arrancado y funcionando.