Gem capistrano 简易速成部署方案 (含 deploy.rb 模板)

jesktop · 2012年10月31日 · 最后由 JeskTop 回复于 2013年12月27日 · 12430 次阅读

先在这里放上来自《Agile Web Development with Rails 4th for Rails3.2》的一个 deploy.rb 模板:

# be sure to change these
set:user, 'rubys'
set:domain, 'depot.pragprog.com'
set:application, 'depot'

# adjust if youareusing RVM, remove if youarenot
$:.unshift(File.expand_path('./lib', ENV['rvm_path']))
require "rvm/capistrano"
set:rvm_ruby_string, '1.9.2'
set:rvm_type, :user

# file paths
set:repository, "#{user}@#{domain}:git/#{application}.git"
set:deploy_to, "/home/#{user}/#{domain}"
# distribute your applications across servers (the instructions below putthem
# allon thesame server, defined above as 'domain', adjust as necessary)

role :app, domain
role :web, domain
role :db, domain, :primary => true
# youmight need to setthis if youaren't seeing password prompts
# default_run_options[:pty] = true
# As Capistrano executes in a non-interactive mode andtherefore doesn't cause
# anyof your shell profile scripts to be run, thefollowing might be needed
# if (for example) youhave locally installed gems or applications. Note:
# this needs to contain thefull values forthevariables set, notsimply
# thedeltas.
# default_environment['PATH']='<your paths>:/usr/local/bin:/usr/bin:/bin'
# default_environment['GEM_PATH']='<your paths>:/usr/lib/ruby/gems/1.8'

# miscellaneous options
set:deploy_via, :remote_cache
set:scm, 'git'
set:branch, 'master'
set:scm_verbose, true
set:use_sudo, false
set:rails_env, :production

namespace :deploy do
  desc "cause Passenger to initiate a restart"

  task :restart do
    run"touch #{current_path}/tmp/restart.txt"
  end

  desc "reload thedatabase with seed data"
  task :seed do
    run"cd#{current_path}; rake db:seed RAILS_ENV=#{rails_env}"
  end
end

after "deploy:update_code", :bundle_install
desc "install thenecessary prerequisites"

task :bundle_install, :roles => :app do
  run"cd#{release_path} && bundle install"
end

这个模板非常方便,因为我拿在手里了,加上自己的配置就可以直接使用了。 现在这里我介绍一下怎么使用,需要修改一些什么。

首先在加入一个 gem,gem 'capistrano'。然后创建相关文件,只需要执行一个命令就可以:

$ capify .
[add] writing './Capfile'
[add] writing './config/deploy.rb'
[done] capified!

这时候生成两个文件。如果在用使用 3.1 以上版本的 Rails,在 Capfile 加上一句:

load 'deploy/assets'    //assets操作

然后剩下的就是 deploy.rb 上的了,我发一下我的配置,然后备注一下,到时候大家按照我那个配置设置一下就可以了,如下:

require "bundler/capistrano"   #部署时运行bundle
set :user, 'deploy'            #存放web的用户名
set :domain, '106.XX.XX.XX'        #服务器IP
set :application, 'ruby-china.org'    #项目文件名,既将会在user里面创建这个名字的文件夹
# adjust if you are using RVM, remove if you are not
$:.unshift(File.expand_path('./lib', ENV['rvm_path']))
require "rvm/capistrano"
set :rvm_ruby_string, '1.9.3'
set :rvm_type, :user
# file paths
set :repository, "git@#{domain}:ruby-china.git"  #git所存在的地址,我存放在自己的服务器中
set :deploy_to, "/home/deploy/ruby-china.org"  #部署的地址
# distribute your applications across servers (the instructions below put them
# all on the same server, defined above as 'domain', adjust as necessary)
role :app, domain
role :web, domain
role :db, domain, :primary => true
ssh_options[:forward_agent] = true  #forward_agent方式

# miscellaneous options
set :deploy_via, :remote_cache
set :scm, 'git'
set :branch, 'master'
set :scm_verbose, true
set :use_sudo, false
set :rails_env, "production"

namespace :deploy do
  desc "cause Passenger to initiate a restart"
  task :restart do
    run "touch #{current_path}/tmp/restart.txt"
  end
  desc "reload the database with seed data"
  task :seed do
    run "cd #{current_path}; rake db:seed RAILS_ENV=#{rails_env}"
  end
end

注意:这里涉及一个叫“forward_agent 方式”,简单的来说就是服务器在 clone git 的时候是不成功的,因为他的 ssh 公钥并不在 git 的账户中,而我们电脑的公钥已经存放在 git 服务器里了,所以可以直接 push 或者 pull 操作 git,所以这类需要使用 ssh agent forward,也就是在部署时,VPS 使用你的 SSH 密钥。参考: Using ssh agent forwarding

git 的地址当然也可以在 github 上,但是我觉得竟然有 VPS 了,放在自己的 VPS 上更加方便。我以前有个教人在自己 VPS 上部署 GIT 的方法:Linode VPS 小组级 Git 服务器搭建

如果你使用的个别东西不一样就需要参考 capistrano 的 wiki 进行修改了,例如你用的不是 git,服务器不是 Passenger 等等。

写好 deploy.rb 后的事情就不多了,首先把修改过的内容 push 到 git 上面。然后开始部署了,第一次部署需要运行:

$ cap deploy:setup
$ cap deploy:check
$ cap deploy:migrations

上条命令下来,如果没有问题就已经成功的设置成功了,然后进行发布:

$ cap deploy

非常方便的就把网站部署到 VPS 上了,如果以后有修改了东西也非常容易发布:

$ git add .
$ git commit -m "add capfiles"
$ git push
$ cap deploy

非常的简单方便,只需要几条命令,服务器上的信息就更新了。这个文章介绍的比较简单,没有去讲一些任务的写法,就简单的项目来说精简够用了。需要更深入的了解可以通过以上方式: Capistrano 2.x Getting Started capistrano wiki

after "deploy:update_code", :bundle_install
desc "install the necessary prerequisites"
task :bundle_install, :roles => :app do
  run "cd #{release_path} && bundle install"
end

上面这部分有必要写吗?

require "bundler/capistrano" #部署时运行bundle 已经有这个了啊 https://github.com/carlhuda/bundler/blob/master/lib/bundler/capistrano.rb#L8

#1 楼 @happypeter 其实我也不太清楚什么原因,之前没有加require "bundler/capistrano" 第一次部署的时候他不会自动的 bundle install。

#1 楼 @happypeter 老师为什么 set :use_sudo, false 我在我的项目中也时 false 但一直无法成功,在你的视频里,我注意到你改成了 true ,不知道原因,求老师指教

#3 楼 @tiseheaini

set :use_sudo, false. By default, Capistrano will try to use sudo to do certain operations (setting up your servers, restarting your application, etc.). If you are on a shared host, sudo might be unavailable to you, or maybe you just want to avoid using sudo.

这个好像是与你的项目和 rvm 部署的关系吧。有些人把 rvm 部署到 root 里的,就需要 sudo 了。

#3 楼 @tiseheaini
I used #{try_sudo} in my deploy.rb whenever I want to run some command as root, and

  • #{try_sudo} will return sudo when set :use_sudo, true,
  • return ""(empty string) when set :use_sudo, false

as clearly shown in the source code https://github.com/capistrano/capistrano/blob/master/lib/capistrano/recipes/deploy.rb#L155

@happypeter 我看到了这句话 always wanted sudo to run as a particular user, you could do set(:admin_runner, "bob"). 意思是说,我可以 set :admin_runner, "tian" 然后用我的账号去登陆系统,然后执行命令,还是说,先用 root 运行一些命令,然后再改回 false,以后的部署就不需要使用 root 了??? 我的理解对吗??

没太明白你的意思。

使用 root 是存在潜在风险的,因为 root 创建的东西,其他用户一般是没有权限去改动的。只要你记住这一点,你就可以安心的使用 sudo 了,方式很多效果都一样。

上面的 bob 必须是系统上的 sudoer 才可以。

#7 楼 @happypeter 谢谢老师指导,我好像懂了点,linux 还是小白呀!!

正好用的上,部署成功。。

我也刚好看到这里

@JeskTop 我的执行 migrations 报错,能帮我看看怎么回事吗?

  * executing `deploy:migrations'
  * executing `deploy:update_code'
    updating the cached checkout on all servers
    executing locally: "git ls-remote [email protected]:git/depot.git master"
    command finished in 404ms
  * executing "if [ -d /home/william/depot.linuxcbt.com/shared/cached-copy ]; then cd /home/william/depot.linuxcbt.com/shared/cached-copy && git fetch  origin && git fetch --tags  origin && git reset  --hard a6c236f29dd7ca5547f9d4a371c1919227245a09 && git clean  -d -x -f; else git clone [email protected]:git/depot.git /home/william/depot.linuxcbt.com/shared/cached-copy && cd /home/william/depot.linuxcbt.com/shared/cached-copy && git checkout -b deploy a6c236f29dd7ca5547f9d4a371c1919227245a09; fi"
    servers: ["depot.linuxcbt.com"]
    [depot.linuxcbt.com] executing command
 ** [depot.linuxcbt.com :: out] HEAD is now at a6c236f bundle gems
    command finished in 1010ms
    copying the cached version to /home/william/depot.linuxcbt.com/releases/20121104135345
  * executing "cp -RPp /home/william/depot.linuxcbt.com/shared/cached-copy /home/william/depot.linuxcbt.com/releases/20121104135345 && (echo a6c236f29dd7ca5547f9d4a371c1919227245a09 > /home/william/depot.linuxcbt.com/releases/20121104135345/REVISION)"
    servers: ["depot.linuxcbt.com"]
    [depot.linuxcbt.com] executing command
    command finished in 32ms
  * executing `deploy:finalize_update'
    triggering before callbacks for `deploy:finalize_update'
  * executing `deploy:assets:symlink'
  * executing "rm -rf /home/william/depot.linuxcbt.com/releases/20121104135345/public/assets &&\\\n        mkdir -p /home/william/depot.linuxcbt.com/releases/20121104135345/public &&\\\n        mkdir -p /home/william/depot.linuxcbt.com/shared/assets &&\\\n        ln -s /home/william/depot.linuxcbt.com/shared/assets /home/william/depot.linuxcbt.com/releases/20121104135345/public/assets"
    servers: ["depot.linuxcbt.com"]
    [depot.linuxcbt.com] executing command
    command finished in 8ms
  * executing "chmod -R g+w /home/william/depot.linuxcbt.com/releases/20121104135345"
    servers: ["depot.linuxcbt.com"]
    [depot.linuxcbt.com] executing command
    command finished in 10ms
  * executing "rm -rf /home/william/depot.linuxcbt.com/releases/20121104135345/log /home/william/depot.linuxcbt.com/releases/20121104135345/public/system /home/william/depot.linuxcbt.com/releases/20121104135345/tmp/pids &&\\\n      mkdir -p /home/william/depot.linuxcbt.com/releases/20121104135345/public &&\\\n      mkdir -p /home/william/depot.linuxcbt.com/releases/20121104135345/tmp &&\\\n      ln -s /home/william/depot.linuxcbt.com/shared/log /home/william/depot.linuxcbt.com/releases/20121104135345/log &&\\\n      ln -s /home/william/depot.linuxcbt.com/shared/system /home/william/depot.linuxcbt.com/releases/20121104135345/public/system &&\\\n      ln -s /home/william/depot.linuxcbt.com/shared/pids /home/william/depot.linuxcbt.com/releases/20121104135345/tmp/pids"
    servers: ["depot.linuxcbt.com"]
    [depot.linuxcbt.com] executing command
    command finished in 15ms
  * executing "find /home/william/depot.linuxcbt.com/releases/20121104135345/public/images /home/william/depot.linuxcbt.com/releases/20121104135345/public/stylesheets /home/william/depot.linuxcbt.com/releases/20121104135345/public/javascripts -exec touch -t 201211041353.45 {} ';'; true"
    servers: ["depot.linuxcbt.com"]
    [depot.linuxcbt.com] executing command
*** [err :: depot.linuxcbt.com] find: `/home/william/depot.linuxcbt.com/releases/20121104135345/public/images'
*** [err :: depot.linuxcbt.com] : No such file or directory
*** [err :: depot.linuxcbt.com] find: `/home/william/depot.linuxcbt.com/releases/20121104135345/public/stylesheets': No such file or directory
*** [err :: depot.linuxcbt.com] find: `/home/william/depot.linuxcbt.com/releases/20121104135345/public/javascripts': No such file or directory
    command finished in 14ms
    triggering after callbacks for `deploy:update_code'
  * executing `deploy:assets:precompile'
  * executing "cd /home/william/depot.linuxcbt.com/releases/20121104135345 && rake RAILS_ENV=production RAILS_GROUPS=assets assets:precompile"
    servers: ["depot.linuxcbt.com"]
    [depot.linuxcbt.com] executing command
*** [err :: depot.linuxcbt.com] sh: 1: rake: not found
    command finished in 11ms
failed: "sh -c 'cd /home/william/depot.linuxcbt.com/releases/20121104135345 && rake RAILS_ENV=production RAILS_GROUPS=assets assets:precompile'" on depot.linuxcbt.com

前面的命令都没有报错

@williamherry

*** [err :: depot.linuxcbt.com] find: `/home/william/depot.linuxcbt.com/releases/20121104135345/public/images'
*** [err :: depot.linuxcbt.com] : No such file or directory
*** [err :: depot.linuxcbt.com] find: `/home/william/depot.linuxcbt.com/releases/20121104135345/public/stylesheets': No such file or directory
*** [err :: depot.linuxcbt.com] find: `/home/william/depot.linuxcbt.com/releases/20121104135345/public/javascripts': No such file or directory
    command finished in 14ms

在这里报错的,不知道为什么会提示你没有/images,/stylesheets,/javascripts 这 3 个文件夹。 http://stackoverflow.com/questions/3023857/capistrano-and-deployment-of-a-website-from-github 这里有解决方法,不太理解为什么你那会出现这个问题呢?

谢谢分享,成功部署. 但是有个问题,线上的 database.yml 和本地开发用的是不一样。 而且 database.yml 是放在了 gitignore 里面了的,git 管理的是 database.yml. 我想问这种情况在部署的时候怎么操作呢? 是否在第一次运行 cap deploy 后,然后手动登上服务器,跑到 current 目录下面去,修改 database.yml?

#13 楼 @small_fish__ http://ruby-china.org/topics/1768 看看这贴的方法可以解决你的问题不?

今天本地一台机器部署,就报告 bundle: not found 错误,求解释

匿名 #16 2013年07月26日

你好,刚接触 ruby on rails 没多久,按照你的教程,发布到服务器上去了后,我通过 ip 访问,报 403 到错误,我到服务器是 nginx,还有我在服务器上好像也没找到我这个项目代码。

#16 楼 @huberydu 你得先看看,项目下 log 的 production.log 显示什么错误。

web 和 DB 位于不同服务器 deploy.rb 怎样配置?谢谢 #17 楼 @JeskTop @happypeter

$:.unshift(File.expand_path('./lib', ENV['rvm_path'])) 这句是做什么用的,我加上这句后会报错,然后去掉后就可以了~

#14 楼 @JeskTop 请问咋样可以不用 forward_agent 么? 我在 windows 下,forward agent 貌似有问题。 我是在 VPS 上又生成了一个 ssh key 然后加到 github ssh keys 里面。这样应该就可以访问 git repo 了 但是不知道其余的部分怎么改

#20 楼 @cqcn1991 把 vps 部署的 id 的公钥和你电脑的公钥都加到 github ssh keys 里,就可以了。

22 楼 已删除

#21 楼 @JeskTop 对了,想请教一下。我用 git bash ssh 连接我的服务器,为什么隔一段时间就掉线了?

24 楼 已删除

#21 楼 @JeskTop 再问个问题…… 要 run migration 的话,还是直接 cap deploy 就行吗?

#25 楼 @cqcn1991 在这个模板里,migration 需要运行cap deploy:migrations,需要特点的 task 可以自己独立写一个的。

xiaoxiao capistrano 部署出现问题 提及了此话题。 04月03日 10:56
需要 登录 后方可回复, 如果你还没有账号请 注册新账号