使用Capistrano3、Nginx、Puma、GitHub和RVM将Rails4API部署到AmazonEC2的示例?

使用Capistrano3、Nginx、Puma、GitHub和RVM将Rails4API部署到AmazonEC2的示例?,nginx,amazon-ec2,ruby-on-rails-4,capistrano,puma,Nginx,Amazon Ec2,Ruby On Rails 4,Capistrano,Puma,我在GitHub上有一个Rails 4 API项目,我正在尝试使用Capistrano 3将它从我的MacBook Pro部署到两个使用SSH密钥的Amazon AWS EC2 Ubuntu实例——一个是app/web服务器,另一个是PostgreSQL数据库服务器。app/web服务器通过RVM安装了最新的Ruby 2,并将通过Nginx/Puma提供API。Nginx将承载多个站点,其中一个就是这个API。以下是我正在使用的相关宝石: gem“capistrano”,“~>3.0.0” 宝

我在GitHub上有一个Rails 4 API项目,我正在尝试使用Capistrano 3将它从我的MacBook Pro部署到两个使用SSH密钥的Amazon AWS EC2 Ubuntu实例——一个是app/web服务器,另一个是PostgreSQL数据库服务器。app/web服务器通过RVM安装了最新的Ruby 2,并将通过Nginx/Puma提供API。Nginx将承载多个站点,其中一个就是这个API。以下是我正在使用的相关宝石:

  • gem“capistrano”,“~>3.0.0”
  • 宝石“capistrano rails”
  • 宝石“capistrano捆绑机”
  • gem“capistrano rvm”,“~>0.0.2”
  • 宝石“capistrano puma”,github:“seuros/capistrano puma”
到目前为止,我还没有发现完整的Capistrano3配置示例使用Puma,但是,尽管这两个宝石对Rails社区很重要,我确信GitHub上一定有一个包含这两个宝石的Rails工作库

我已经看过Capistrano 3的官方文档了。我对Capistrano 2和Capistrano 3之间的差异有疑问,希望看到一个完整的Capistrano 3示例来理解差异。理想情况下,我正在寻找一个开源的GitHub存储库,其中包含所有已完成的配置文件(Capistrano 3PumaNginx),并可供我参考


谢谢大家!

如果有人要求,我会补充我的答案,但因为这很简单,我只给你列一个清单。 基本上,有了Capistrano 3和Puma 2.6,这里就足够让你继续前进了:

  • puma
    添加到
    production
    组中的
    Gemfile
  • 需要来自
    Capfile
    'capistrano/puma'
  • 如果需要,在
    config/deploy.rb
    中设置任何puma选项
  • 运行
    cap puma:config
    将puma配置文件复制到服务器
  • 运行
    capdeploy
  • Setup
    nginx
    位于服务器Puma配置中指定的套接字路径的上游
  • 重新启动nginx

  • 这个问题已经很老了,但我有完全相同的设置:Capistrano3、Puma和nginx,所以我认为它仍然可以帮助一些人,特别是因为Puma现在是Rails5的默认设置。我的项目不是开源的,所以我无法指向Github公共存储库,但这里是我的完整Capistrano配置,供任何人查看。几个月来,它一直在完美地工作

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

    #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 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
    
    # 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
    
    #config/deploy.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 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
    
    # 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
    
    #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

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

    阿德里安,我很感谢你的回复,但我想在这里详细记录这些细节,而不仅仅是一份高层次的清单。您是否愿意修改Capistrano 3、Nginx和Puma的完整配置?感谢您的深入回答!