美文网首页一亩三分地
ruby 2.4.3 + rails5 +capistrano

ruby 2.4.3 + rails5 +capistrano

作者: 舒官人 | 来源:发表于2019-01-27 15:10 被阅读0次

    我是时候用rbenv构建项目,如果用的rvm某些gem需要改变成对应rvm的gem

    服务器环境搭建请看这里

    大体步骤:

    服务器的ssh key记得设置好,并且服务器能访问git项目
    安装相应gem
    配置puma,capistrano相关文件
    配置nginx(ssl证书申请请自行百度)
    提交代码到git
    执行cap命令

    安装capistrano

    capistrano github地址

    在gemfile中添加

    group :development do
      gem "capistrano", "~> 3.11", require: false #基本gem
      gem 'capistrano-rails', '~> 1.1', require: false
      gem 'capistrano-bundler', '~> 1.1', require: false
      gem 'capistrano-rbenv'  #如果输rvm请改成rvm
    end
    

    执行

    bundle install
    cap install

    在项目结构中将出现以下文件

    ├── Capfile
    ├── config
    │ ├── deploy
    │ │ ├── production.rb
    │ │ └── staging.rb
    │ └── deploy.rb
    └── lib
    └── capistrano
    └── tasks

    下面是相关指令(Command-line usage)

    list all available tasks
    bundle exec cap -T
    deploy to the staging environment
    bundle exec cap staging deploy
    deploy to the production environment
    bundle exec cap production deploy
    simulate deploying to the production environment
    does not actually do anything
    bundle exec cap production deploy --dry-run
    list task dependencies
    bundle exec cap production deploy --prereqs
    trace through task invocations
    bundle exec cap production deploy --trace
    lists all config variable before deployment tasks
    bundle exec cap production deploy --print-config-variables

    相关文件配置

    capfile

    # Load DSL and set up stages
    require "capistrano/setup"
    
    # Include default deployment tasks
    require "capistrano/deploy"
    
    require "capistrano/scm/git"
    install_plugin Capistrano::SCM::Git
    require 'capistrano/rbenv'
    require "capistrano/bundler"
    require 'capistrano/rails/migrations'
    require 'sshkit/dsl' #可以去掉
    
    # Load custom tasks from `lib/capistrano/tasks` if you have any defined
    Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
    
    

    config/depoly/prodution.rb

    set :deploy_to,"/var/www/apps/parking"
    
    
    server "服务器IP地址",user:"root", roles: %w{web app db production}
    SSHKit::Backend::Netssh.configure do |ssh|
      ssh.connection_timeout = 30
      ssh.ssh_options = {
          user:"root",
          auth_methods: ['publickey']
      }
    end
    
    namespace :deploy do
      namespace :symlink do
        task :cp_files do
          on "root@服务器IP地址" do
            execute :cp, "-fr","#{release_path}/config/puma.production.rb #{release_path}/config/puma.rb"
          end
        end
      end
      after "deploy:symlink:shared", "deploy:symlink:cp_files"
    end
    

    config/deploy.rb

    # config valid for current version and patch releases of Capistrano
    lock "~> 3.11.0"
    
    # config valid only for current version of Capistrano
    
    set :application, "项目名"
    set :use_sudo,false
    set :repo_url, "git地址"
    set :keep_releases,2
    set :branch,"master"
    set :rails_env,:production
    set :enable_ssl,false
    set :bundle_bins, fetch(:bundle_bins, []).push('rake', 'sidekiq', 'puma', 'rails')
    set :log_level,:info
    # set :ruby
    
    set :linked_dirs, %w{log share/pids share/cache share/sockets public/system public/uploads}
    set :rbenv_map_bins, %w{rake gem bundle ruby rails puma sidekiq} #rbenv命令
    
    
    namespace :sidekiq do
      desc "start sidekiq"
      task :start do
        on roles(:app) do
          within "#{fetch(:deploy_to)}/current" do
            with RAILS_ENV: fetch(:rails_env) do
              # puts capture "kill -QUIT" `cat #{deploy_to}/current/tmp/pids/sidekiq.pid`"
              # execute :kill,"-QUIT","`cat #{deploy_to}/current/tmp/pids/sidekiq.pid`"
              execute :sidekiq,"-i","2","-e","production","-d", "-C","#{deploy_to}/current/config/sidekiq.yml"
            end
          end
        end
      end
    
      desc "restart sidekiq"
      task :restart do
        on roles(:app) do
          within "#{fetch(:deploy_to)}/current" do
            with RAILS_ENV: fetch(:rails_env) do
              # puts capture "kill -QUIT" `cat #{deploy_to}/current/tmp/pids/sidekiq.pid`"
              execute :kill,"-QUIT","`cat #{deploy_to}/current/share/pids/sidekiq.pid`"
              execute :sidekiq,"-i","2","-e","production","-d", "-C","#{deploy_to}/current/config/sidekiq.yml"
            end
          end
        end
      end
    
      desc "stop sidekiq"
      task :stop do
        on roles(:app) do
          within "#{fetch(:deploy_to)}/current" do
            with RAILS_ENV: fetch(:rails_env) do
              # puts capture "kill -QUIT" `cat #{deploy_to}/current/tmp/pids/sidekiq.pid`"
              execute :kill,"-QUIT","`cat #{deploy_to}/current/share/pids/sidekiq.pid`"
              # execute :sidekiq,"-i","2","-e","production","-d", "-c","#{deploy_to}/current/config/sidekiq.yml"
            end
          end
        end
      end
    end
    
    namespace :deploy do
    
      # desc "Update crontab with whenever"
      # task :update_cron do
      #   on roles(:app) do
      #     within "#{fetch(:deploy_to)}/current" do
      #       execute :whenever,"--update-crontab #{fetch(:application)}"
      #     end
      #   end
      # end
    
      desc "rake assets"
      task :compile_assets do
        on roles(:app) do
          within "#{fetch(:deploy_to)}/current" do
            with RAILS_ENV: fetch(:rails_env) do
              execute :rake,"assets:precompile","RAILS_ENV=production"
            end
          end
        end
      end
    
    
    
    
      desc "Start puma"
      task :start_puma do
        on roles(:app) do
          within "#{fetch(:deploy_to)}/current" do
            with RALS_ENV: fetch(:rails_env) do
              execute :puma,"-C","#{deploy_to}/current/config/puma.rb"
            end
          end
        end
      end
    
      desc "Restart puma"
      task :restart_puma do
        on roles(:app) do
          within "#{fetch(:deploy_to)}/current" do
            with RALS_ENV: fetch(:rails_env) do
              execute :kill,"-QUIT","`cat #{deploy_to}/current/share/pids/puma.pid`"
              sleep(5)
              execute :puma,"-C","#{deploy_to}/current/config/puma.rb"
            end
          end
        end
      end
    
    
      desc "Stop puma"
      task :stop_puma do
        on roles(:app) do
          puts capture "kill -QUIT `cat #{deploy_to}/current/share/pids/puma.pid`"
        end
      end
      after :finishing, 'deploy:cleanup'
      after :published, :restart_puma
      after :finishing, 'sidekiq:start'
      after :published, :compile_assets
    end
    

    注意在centos中 sidekiq和puma脚本会出现kill 结束kill -9 pid错误导致后面的不执行,建议用ubuntu。

    配置puma

    puma.rb

    # Puma can serve each request in a thread from an internal thread pool.
    # The `threads` method setting takes two numbers: a minimum and maximum.
    # Any libraries that use thread pools should be configured to match
    # the maximum value specified for Puma. Default is set to 5 threads for minimum
    # and maximum; this matches the default thread size of Active Record.
    #
    threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
    threads threads_count, threads_count
    
    # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
    #
    port        ENV.fetch("PORT") { 3000 }
    
    # Specifies the `environment` that Puma will run in.
    #
    environment ENV.fetch("RAILS_ENV") { "development" }
    
    # Specifies the number of `workers` to boot in clustered mode.
    # Workers are forked webserver processes. If using threads and workers together
    # the concurrency of the application would be max `threads` * `workers`.
    # Workers do not work on JRuby or Windows (both of which do not support
    # processes).
    #
    # workers ENV.fetch("WEB_CONCURRENCY") { 2 }
    
    # Use the `preload_app!` method when specifying a `workers` number.
    # This directive tells Puma to first boot the application and load code
    # before forking the application. This takes advantage of Copy On Write
    # process behavior so workers use less memory. If you use this option
    # you need to make sure to reconnect any threads in the `on_worker_boot`
    # block.
    #
    # preload_app!
    
    # If you are preloading your application and using Active Record, it's
    # recommended that you close any connections to the database before workers
    # are forked to prevent connection leakage.
    #
    # before_fork do
    #   ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord)
    # end
    
    # The code in the `on_worker_boot` will be called if you are using
    # clustered mode by specifying a number of `workers`. After each worker
    # process is booted, this block will be run. If you are using the `preload_app!`
    # option, you will want to use this block to reconnect to any threads
    # or connections that may have been created at application boot, as Ruby
    # cannot share connections between processes.
    #
    # on_worker_boot do
    #   ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
    # end
    #
    
    # Allow puma to be restarted by `rails restart` command.
    plugin :tmp_restart
    
    

    增加config/puma.production.rb文件

    # Puma can serve each request in a thread from an internal thread pool.
    # The `threads` method setting takes two numbers a minimum and maximum.
    # Any libraries that use thread pools should be configured to match
    # the maximum value specified for Puma. Default is set to 5 threads for minimum
    # and maximum, this matches the default thread size of Active Record.
    #
    threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
    threads threads_count, threads_count
    
    
    environment ENV.fetch("RAILS_ENV") { "production" }
    
    # Specifies the number of `workers` to boot in clustered mode.
    # Workers are forked webserver processes. If using threads and workers together
    # the concurrency of the application would be max `threads` * `workers`.
    # Workers do not work on JRuby or Windows (both of which do not support
    # processes).
    #
    app_dir = File.expand_path("../..", __FILE__)
    workers ENV.fetch("WEB_CONCURRENCY") { 2 }
    shared_dir = "#{app_dir}/share"
    
    
    
    stdout_redirect "#{app_dir}/log/puma.stdout.log", "#{app_dir}/log/puma.stderr.log", true
    
    
    pidfile "#{shared_dir}/pids/puma.pid"
    state_path "#{shared_dir}/pids/puma.state"
    activate_control_app
    
    on_worker_boot do
      require "active_record"
      ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
      ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")["production"])
    end
    
    worker_timeout 60
    daemonize true
    bind "unix:///tmp/项目名.sock"
    
    # preload_app!
    
    # Use the `preload_app!` method when specifying a `workers` number.
    # This directive tells Puma to first boot the application and load code
    # before forking the application. This takes advantage of Copy On Write
    # process behavior so workers use less memory. If you use this option
    # you need to make sure to reconnect any threads in the `on_worker_boot`
    # block.
    #
    # preload_app!
    
    # The code in the `on_worker_boot` will be called if you are using
    # clustered mode by specifying a number of `workers`. After each worker
    # process is booted this block will be run, if you are using `preload_app!`
    # option you will want to use this block to reconnect to any threads
    # or connections that may have been created at application boot, Ruby
    # cannot share connections between processes.
    #
    # on_worker_boot do
    #   ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
    # end
    
    # Allow puma to be restarted by `rails restart` command.
    plugin :tmp_restart
    

    bind "unix:///tmp/项目名.sock" 请替换你的项目名, 第二在centos系统中部署请求是会导致502错误 原因为 /tmp/项目名.sock 不是一个文件夹(详细信息在nginx的错误日志中),ubuntu没问题,具体什么原因还不清楚

    配置nginx

    注:centos中 通过yum安装nginx没有sites-enable文件夹,需要自行创建(自行百度很简单),ubuntu会有此文件夹
    我们的配置文件放在sites-enable中,适合多个项目的时候。

    安装好nginx之后进入

    cd /etc/nginx/sites-enabled/ 删除默认的default文件,新建项目名.conf文件

    文件内容如下:

    upstream parking {
       server unix:/tmp/项目名.sock fail_timeout=0;  #需要和puma.production.rb中的bind "unix:///tmp/项目名.sock" 对应 这里是一个/  PUMA是三个/
    }
    server {
     # listen 80 default_server;
      listen 443 default_server ssl;
      charset utf-8;
      server_name 域名;
      ssl on; #开启则只能https访问想http也能访问请注释
      ssl_certificate /etc/ssl/parking.pem; #ssl证书路劲
      ssl_certificate_key  /etc/ssl/parking.key; #ssl证书路劲
      ssl_session_timeout 5m;
      ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
      ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
      ssl_prefer_server_ciphers on;
      access_log /var/www/apps/项目名/current/log/access.log;
      error_log /var/www/apps/项目名/current/log/error.log;
    
    
      root /var/www/apps/项目名/current/public; #rails项目路劲
      location / {
        try_files /index.html $uri @ruby;
      }
    
      location @ruby {
        proxy_pass http://项目名;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-Proto http;
        proxy_redirect off;
      }
    
      error_page 500 502 503 504 /500.html;
      client_max_body_size 500M;
      keepalive_timeout 1800;
    }
    

    配合好之后执行

    nginx -s reload 重新加载配置文件。

    部署

    1. 将代码提交git
    2. 在本地项目根目录执行 cap production depoly
    3. 部署的时候出现错误一般都会有提示如何解决 或者百度都能解决

    出现的相关问题集合

    1. libcurl问题

    服务器执行 apt-get install libcurl4-openssl-dev

    2. bundle stderr: /usr/bin/env: 'bundle': No such file or directory

    capfile 未引入require "capistrano/bundler"

    3. 控制台未出现migrate相关操作

    capfile 未引入 require 'capistrano/rails/migrations'

    相关文章

      网友评论

        本文标题:ruby 2.4.3 + rails5 +capistrano

        本文链接:https://www.haomeiwen.com/subject/jlogjqtx.html