¿Rails 4 ejemplo de despliegue API para Amazon EC2 usando Capistrano 3, Nginx, Puma, GitHub y RVM?
amazon-ec2 ruby-on-rails-4 (2)
Aumentaré mi respuesta si se solicita, pero como esto es bastante simple, solo te haré una lista. Básicamente, con Capistrano 3 y Puma 2.6 esto es suficiente para que empieces:
- Agrega
puma
aGemfile
en el grupo deproduction
. - Requerir
''capistrano/puma''
desdeCapfile
. - Configure cualquier opción de puma en
config/deploy.rb
si es necesario. - Ejecute
cap puma:config
para copiar el archivo de configuración de puma en el servidor. - Ejecutar
cap <stage> deploy
. - Configure
nginx
''s upstream a la ruta del socket especificada en la configuración de Puma del servidor. - Reinicie
nginx
.
Tengo un proyecto Rails 4 API en GitHub, y estoy intentando implementarlo desde mi MacBook Pro usando Capistrano 3 o dos instancias de Amazon AWS EC2 Ubuntu usando claves SSH: una es la aplicación / servidor web, y la otra es PostgreSQL servidor de base de datos. La aplicación / servidor web tiene el último Ruby 2 vía RVM, y servirá la API con Nginx / Puma . Nginx alojará múltiples sitios, uno de los cuales es esta API. Estas son las gemas relevantes que estoy usando:
- gema ''capistrano'', ''~> 3.0.0''
- gemas ''capistrano-rails''
- gema ''capistrano-bundler''
- gema ''capistrano-rvm'', ''~> 0.0.2''
- gema ''capistrano-puma'', github: "seuros / capistrano-puma"
Hasta ahora, no he encontrado un ejemplo completo de configuración de Capistrano 3 que use Puma , pero por más importantes que estas dos gemas sean para la comunidad de Rails, estoy seguro de que debe haber un repositorio de Rails en funcionamiento en alguna parte de GitHub que incluya estos.
Ya he pasado por la documentación oficial de Capistrano 3. Tengo problemas con las diferencias entre Capistrano 2 y Capistrano 3, y me gustaría ver un ejemplo completo de Capistrano 3 para entender las diferencias. Idealmente, estoy buscando un repositorio de código abierto de GitHub que tenga todos los archivos de configuración completados ( Capistrano 3 , Puma , Nginx ) y trabajo al que pueda hacer referencia.
¡Gracias!
Esta pregunta es bastante antigua, pero tengo exactamente la misma configuración: Capistrano 3, Puma y nginx, así que creo que todavía puede ayudar a alguien, especialmente porque ahora Puma es el predeterminado para Rails 5. Mi proyecto no es de código abierto, así que no puedo apuntar a un repositorio público de Github, pero esta es mi configuración completa de Capistrano para que cualquiera pueda echarle un vistazo. Ha funcionado impecablemente durante meses.
Para iniciar Puma correctamente en el servidor de producción al reiniciar EC2 / crear una nueva instancia, mira mi respuesta aquí:
El reinicio de Puma falla al reiniciarse usando EC2 + Rails + Nginx + Capistrano
# config / puma.rb
workers Integer(ENV[''WEB_CONCURRENCY''] || 2)
threads_count = Integer(ENV[''MAX_THREADS''] || 5)
threads threads_count, threads_count
preload_app!
rackup DefaultRackup
port ENV[''PORT''] || 3000
environment ENV[''RACK_ENV''] || ''development''
on_worker_boot do
# Worker specific setup for Rails 4.1+
# See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
ActiveRecord::Base.establish_connection
end
# config / deploy.rb
# config valid only for current version of Capistrano
lock ''3.4.0''
set :application, ''deseov12''
set :repo_url, ''[email protected]:augustosamame/deseov12.git''
set :user, ''deploy''
set :branch, :master
set :deploy_to, ''/home/deploy/deseov12''
set :rails_env, ''production''
set :pty, true
set :linked_files, %w{config/database.yml config/application.yml}
set :linked_dirs, %w{log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system public/uploads}
set :keep_releases, 3
set :rvm_type, :user
set :rvm_ruby_version, ''ruby-2.2.4'' # Edit this if you are using MRI Ruby
set :delayed_job_command, "bin/delayed_job"
set :puma_rackup, -> { File.join(current_path, ''config.ru'') }
set :puma_state, "#{shared_path}/tmp/pids/puma.state"
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
set :puma_bind, "unix://#{shared_path}/tmp/sockets/puma.sock" #accept array for multi-bind
set :puma_conf, "#{shared_path}/puma.rb"
set :puma_access_log, "#{shared_path}/log/puma_error.log"
set :puma_error_log, "#{shared_path}/log/puma_access.log"
set :puma_role, :app
set :puma_env, fetch(:rack_env, fetch(:rails_env, ''production''))
set :puma_threads, [0, 8]
set :puma_workers, 0
set :puma_worker_timeout, nil
set :puma_init_active_record, true
set :puma_preload_app, false
#load ''lib/capistrano/tasks/seed.rb''
namespace :db do
desc ''Resets DB without create/drop''
task :nuke do
on primary :db do
within release_path do
with rails_env: fetch(:stage) do
execute :rake, ''db:reset db:migrate db:seed''
end
end
end
end
end
# Default branch is :master
# ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp
# Default deploy_to directory is /var/www/my_app_name
# set :deploy_to, ''/var/www/my_app_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, fetch(:linked_files, []).push(''config/database.yml'', ''config/secrets.yml'')
# Default value for linked_dirs is []
# set :linked_dirs, fetch(:linked_dirs, []).push(''log'', ''tmp/pids'', ''tmp/cache'', ''tmp/sockets'', ''vendor/bundle'', ''public/system'')
# 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
namespace :puma do
desc ''Create Directories for Puma Pids and Socket''
task :make_dirs do
on roles(:app) do
execute "mkdir #{shared_path}/tmp/sockets -p"
execute "mkdir #{shared_path}/tmp/pids -p"
end
end
before :start, :make_dirs
end
namespace :deploy do
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
#Capfile
# Load DSL and set up stages
require ''capistrano/setup''
# Include default deployment tasks
require ''capistrano/deploy''
# Include 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
# https://github.com/capistrano/passenger
#
require ''capistrano/rvm''
require ''capistrano/bundler''
require ''capistrano/rails/assets''
require ''capistrano/rails/migrations''
require ''capistrano/puma''
require ''capistrano/delayed-job''
# require ''capistrano/passenger''
# require ''capistrano/rbenv''
# require ''capistrano/chruby''
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob(''lib/capistrano/tasks/*.rake'').each { |r| import r }
# config / deploy / production.rb
# server-based syntax
# ======================
# Defines a single server with a list of roles and multiple properties.
# You can define all roles on a single server, or split them:
# server ''example.com'', user: ''deploy'', roles: %w{app db web}, my_property: :my_value
# server ''example.com'', user: ''deploy'', roles: %w{app web}, other_property: :other_value
# server ''db.example.com'', user: ''deploy'', roles: %w{db}
# your actual server ip address should go here:
server ''xx.xx.xx.xxx'', user: ''deploy'', roles: %w{web app db} #Deploy
# server ''xx.xx.xx.xxx'', user: ''deploy'', roles: %w{web app db} #Prod
# lib / capistrano / tasks
namespace :deploy do
desc ''Runs rake db:seed for SeedMigrations data''
task :seed => [:set_rails_env] do
on primary fetch(:migration_role) do
within release_path do
with rails_env: fetch(:rails_env) do
execute :rake, "db:seed"
end
end
end
end
after ''deploy:migrate'', ''deploy:seed''
desc ''Set config/puma.rb-symlink for upstart''
task :pumaconfigln do
on roles(:app) do
execute "ln -s #{sharedpath}/puma.rb #{fetch(:deployto)}/current/config/puma.rb"
end
end
after :finishing, :pumaconfigln
end
Configuración del servidor Nginx:
# etc / nginx / sites-enabled / default
# You may add here your
# server {
# ...
# }
# statements for each of your virtual hosts to this file
##
# You should look at the following URL''s in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# http://wiki.nginx.org/Pitfalls
# http://wiki.nginx.org/QuickStart
# http://wiki.nginx.org/Configuration
#
# Generally, you will want to move this file somewhere, and start with a clean
# file but keep this around for reference. Or just disable in sites-enabled.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##
upstream app {
# Path to Puma SOCK file, as defined previously
server unix:/home/deploy/deseov12/shared/tmp/sockets/puma.sock fail_timeout=0;
}
server {
listen 80;
server_name localhost;
root /home/deploy/deseov12/current/public;
try_files $uri/index.html $uri @app;
location / {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Connection '''';
proxy_pass http://app;
}
location ~ ^/(assets|fonts|system)/|favicon.ico|robots.txt {
gzip_static on;
expires max;
add_header Cache-Control public;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
server {
listen 443 default ssl;
server_name lodeseo.com;
root /home/deploy/deseov12/current/public;
ssl on;
ssl_certificate /etc/nginx/ssl/www_lodeseo_com_bundle.crt;
ssl_certificate_key /etc/nginx/ssl/www_lodeseo_com.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ''EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'';
#ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
location ~ ^/(assets|fonts|system)/|favicon.ico|robots.txt {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri @app;
location @app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
#proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_pass http://app;
}
}
# Only for nginx-naxsi used with nginx-naxsi-ui : process denied requests
#location /RequestDenied {
# proxy_pass http://127.0.0.1:8080;
#}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
#error_page 500 502 503 504 /50x.html;
#location = /50x.html {
# root /usr/share/nginx/html;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ /.php$ {
# fastcgi_split_path_info ^(.+/.php)(/.+)$;
# # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
#
# # With php5-cgi alone:
# fastcgi_pass 127.0.0.1:9000;
# # With php5-fpm:
# fastcgi_pass unix:/var/run/php5-fpm.sock;
# fastcgi_index index.php;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache''s document root
# concurs with nginx''s one
#
#location ~ //.ht {
# deny all;
#}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# root html;
# index index.html index.htm;
#
# location / {
# try_files $uri $uri/ =404;
# }
#}
# HTTPS server
#
#server {
# listen 443;
# server_name localhost;
#
# root html;
# index index.html index.htm;
#
# ssl on;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
#
# ssl_session_timeout 5m;
#
# ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
# ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
# ssl_prefer_server_ciphers on;
#
# location / {
# try_files $uri $uri/ =404;
# }
#}