社区上面关于自动部署的文章比较完整和齐全了,在此,我仅将自己最近用 mina 部署 Rails+sidekiq+unicorn 的整个过程,做一个总结,希望对新手做一个指引,也抛砖引玉,希望更多高手发表自己的部署经验,共勉。
Rails 自动部署,主流的方案有:
刚开始选择了 capistrano,感觉比较折腾,最终选择了 mina。最后发现,选择 mina 是值的,特别是配合 mina-sidekiq,和 mina-unicorn,让整个部署更加简洁,高效。
在 Gemfile 中增加:
gem 'mina'
在相应的 Rails 工作目录,执行
$ mina init
mina init 命令会在 config 目录生成一个默认的配置文件 deploy.rb
项目中,运用到了 sidekiq 做异步队列:
Gemfile 中增加
gem 'mina-sidekiq',:require => false
应用服务器用的 unicorn,使用 mina-unicorn,可以非常方便完成进程的启,停,重启
https://github.com/scarfacedeb/mina-unicorn/blob/master/lib/mina/unicorn/tasks.rb
Gemfile 中增加:
gem 'mina-unicorn', :require => false
注:以下配置都是修改 config/deploy.rb 文件
set :domain, '*.*.*.*'
set :deploy_to, '/data/project/science_read'
set :user, 'deployer'
set :port, '3118'
set :forward_agent, false
其中:domain 为目标主机 IP,deploy_to 为目标主机的部署路径,user 为用户名,port 为 ssh 的端口号。 注:请将自动部署机器的~/.ssh/id_rsa.pub,放置到目标机器的~/.ssh/authorized_keys 列表里面,从而完成自动登陆
set :repository, '[email protected]:hesheng/science_read.git'
set :branch, 'master'
set :sidekiq_pid, "#{deploy_to}/tmp/pids/sidekiq.pid"
set :unicorn_pid, "#{deploy_to}/tmp/pids/unicorn.pid"
set :rvm_path, '/usr/local/rvm/bin/rvm'
task :environment do
invoke :'rvm:use[ruby-2.0.0@default]'
end
set :shared_paths, ['config/database.yml', 'config/yetting.yml','config/symmetric-encryption.yml','log']
以上设置了 log 目录,以及 database.yml,yetting.yml,symmetric-encryption.yml 为所有版本共享
以下是执行 mina setup 命令时,在远程目录机执行的创建目录或者文件的操作
task :setup => :environment do
queue! %[mkdir -p "#{deploy_to}/tmp/sockets/"]
queue! %[mkdir -p "#{deploy_to}/tmp/pids/"]
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/log"]
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/config"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/database.yml"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/yetting.yml"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/symmetric-encryption.yml"]
queue %[echo "-----> Be sure to edit '#{deploy_to}/#{shared_path}/config/database.yml','yetting.yml', 'symmetric-encryption.yml'."]
以下是执行 mina deploy 命令时,执行的任务操作,是整个远程部署的核心
desc "Deploys the current version to the server."
task :deploy => :environment do
to :before_hook do
# Put things to run locally before ssh
end
deploy do
invoke :'git:clone'
invoke :'deploy:link_shared_paths'
invoke :'bundle:install'
invoke :'rails:db_migrate'
invoke :'rails:assets_precompile'
invoke :'deploy:cleanup'
to :launch do
# sidekiq stop accepting new workers
invoke :'sidekiq:quiet'
invoke :'sidekiq:restart'
invoke :'unicorn:restart'
end
end
end
task:deploy,首先从 repository 的 branch 中 clone 一份代码到 deploy_to 目录,然后生成连接目录及文件,执行 bundle, db_migrate,assets_precompile 命令 ,最后会执行 launch,里面的 sidekiq 异步任务的重启,以及 unicorn 进程重启。
编辑,database.yml,yetting.yml,以及 symmetric-encryption.yml 文件,以使其符合正式部署的需求。
listen "/data/project/science_read/tmp/sockets/unicorn.sock", :backlog => 64
pid "/data/project/science_read/tmp/pids/unicorn.pid"
之所以这样修改,是因为,自动部署后,APP_HOME = Rails.root 会从未部署时候的/data/project/science_read/变成/data/project/science_read/current
$ mina deploy
在实际的项目中,可能会定时完成自动部署,比如每小时的 0 分钟时部署一次,crontab 任务
0 * * * * cd /data/project/mina_do_not_remove/science_read && mina deploy
require 'mina/bundler'
require 'mina/rails'
require 'mina/git'
require 'mina/rvm'
require 'mina/unicorn'
require "mina_sidekiq/tasks"
set :domain, '*.*.*.*'
set :deploy_to, '/data/project/science_read'
set :user, 'deployer'
set :port, '3118'
set :forward_agent, false
#设置git地址及分支
set :repository, '[email protected]:hesheng/science_read.git'
set :branch, 'master'
set :rvm_path, '/usr/local/rvm/bin/rvm'
set :shared_paths, ['config/database.yml', 'config/yetting.yml','config/symmetric-encryption.yml','log']
#设置sidekiq的进程保存地址
set :sidekiq_pid, "#{deploy_to}/tmp/pids/sidekiq.pid"
#设置unicorn pid 及 进程启动环境
set :unicorn_pid, "#{deploy_to}/tmp/pids/unicorn.pid"
set :unicorn_env, 'production'
task :environment do
invoke :'rvm:use[ruby-2.0.0@default]'
end
task :setup => :environment do
# unicorn and sidekiq needs a place to store its pid file
queue! %[mkdir -p "#{deploy_to}/tmp/sockets/"]
queue! %[mkdir -p "#{deploy_to}/tmp/pids/"]
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/log"]
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/config"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/database.yml"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/yetting.yml"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/symmetric-encryption.yml"]
queue %[echo "-----> Be sure to edit '#{deploy_to}/#{shared_path}/config/database.yml','yetting.yml', 'symmetric-encryption.yml'."]
queue %[
repo_host=`echo $repo | sed -e 's/.*@//g' -e 's/:.*//g'` &&
repo_port=`echo $repo | grep -o ':[0-9]*' | sed -e 's/://g'` &&
if [ -z "${repo_port}" ]; then repo_port=22; fi ]
end
desc "Deploys the current version to the server."
task :deploy => :environment do
to :before_hook do
# Put things to run locally before ssh
end
deploy do
invoke :'git:clone'
invoke :'deploy:link_shared_paths'
invoke :'bundle:install'
invoke :'rails:db_migrate'
invoke :'rails:assets_precompile'
invoke :'deploy:cleanup'
to :launch do
# sidekiq stop accepting new workers
invoke :'sidekiq:quiet'
invoke :'sidekiq:restart'
invoke :'unicorn:restart'
end
end
end