ruby 2.4.3 + rails5 +capistrano 3 + nginx+ https 部署项目

我是时候用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'

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,932评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,554评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,894评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,442评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,347评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,899评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,325评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,980评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,196评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,163评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,085评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,826评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,389评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,501评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,753评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,171评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,616评论 2 339

推荐阅读更多精彩内容