使用Capistrano 3,Nginx,Puma,GitHub和RVM将Rails 4 API部署到Amazon EC2的示例吗?

问题描述:

我在GitHub上有一个Rails 4 API项目,并且我正在尝试使用SSH密钥将其使用 Capistrano 3 从MacBook Pro部署到两个Amazon AWS EC2 Ubuntu实例-一个是应用程序/web服务器,另一个是PostgreSQL数据库服务器.该应用程序/网络服务器通过RVM具有最新的Ruby 2,并将与 Nginx/Puma 一起提供API. Nginx将托管多个站点,此API就是其中之一.这些是我正在使用的相关宝石:

I have a Rails 4 API project on GitHub, and I'm trying to deploy it from my MacBook Pro using Capistrano 3 to two Amazon AWS EC2 Ubuntu instances using SSH keys - one is the app/web server, and the other is the PostgreSQL database server. The app/web server has the latest Ruby 2 via RVM, and will serve the API with Nginx / Puma. Nginx will host multiple sites, one of which is this API. These are the relevant gems I'm using:

  • 宝石'capistrano','〜> 3.0.0'
  • 宝石'capistrano-rails'
  • 宝石'capistrano-bundler'
  • gem'capistrano-rvm','〜> 0.0.2'
  • gem'capistrano-puma',github:"seuros/capistrano-puma"

到目前为止,我还没有找到使用 Puma 的完整 Capistrano 3 配置示例,但是对于这两个瑰宝对Rails社区同样重要,我是确保在GitHub上的某个地方必须有一个可用的Rails存储库,其中包括这些.

So far, I've found no complete Capistrano 3 config example that uses Puma, but as important as these two gems are to the Rails community, I'm sure there must a working Rails repository somewhere on GitHub that includes these.

我已经阅读过Capistrano 3官方文档.我在Capistrano 2和Capistrano 3之间的区别上遇到了麻烦,并且想看一个完整的Capistrano 3示例来理解这些区别.理想情况下,我正在寻找一个开放源代码的GitHub存储库,该存储库已完成所有配置文件( Capistrano 3 Puma Nginx )并可以正常工作我可以参考.

I've already been through the official Capistrano 3 documentation. I'm having trouble with the differences between Capistrano 2 and Capistrano 3, and would like to see a complete Capistrano 3 example to understand the differences. Ideally, I'm looking for an open source GitHub repository that has all the configuration files completed (Capistrano 3, Puma, Nginx) and working that I can reference.

谢谢!

这个问题已经很老了,但我的设置完全相同:Capistrano 3,Puma和nginx,所以我认为它可能仍然对某人有所帮助,特别是因为Puma现在已经Rails 5的默认设置.我的项目不是开源的,因此我无法指向Github公共存储库,但这是我完整的Capistrano配置,任何人都可以看一下.它已经完美地工作了几个月了.

This question is pretty old but I have the exact same setup: Capistrano 3, Puma and nginx so I figure it may still help someone, especially since Puma is now the default for Rails 5. My project is not open source so I can't point to a Github public repository, but here is my complete Capistrano configuration for anyone to take a look. It has been working flawlessly for months now.

要在EC2重新启动/创建新实例后在生产服务器中正确启动Puma,请在此处查看我的答案:

To properly start Puma in the production server upon EC2 reboot / new instance creation, take a look at my answer here:

Puma重新启动在重新启动时失败使用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, 'git@bitbucket.org: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/任务

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

Nginx服务器配置:

Nginx Server configuration:

#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;
#   }
#}