我是时候用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 重新加载配置文件。
部署
- 将代码提交git
- 在本地项目根目录执行 cap production depoly
- 部署的时候出现错误一般都会有提示如何解决 或者百度都能解决
出现的相关问题集合
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'