本文基于Capistrano 2版本,文中的命令不一定适用于Capistrano 3。

什么是Capistrano?

简单地讲,Capistrano是一个gem。对于不太熟悉Ruby的朋友来说,gem就是一套按照一定规范打包好的Ruby代码,可以类比Java里面的Package。

实际上,Capistrano是专门用来部署rails程序的一套工具。

为什么用它?

Rails应用程序的部署方案十分灵活,适应于不同的生产服务器场景。在实际生产中,rails程序中包含的各类gem和生产服务器上的gem往往版本不一致,这就为部署增加了一些难度。

利用Capistrano进行部署,就能很容易解决这个问题。同时,使用Capistrano部署rails程序,更有一种“敏捷”的感觉。

在进行Rails开发过程中,一个重要的工具就是版本控制,而我们经常用Git。用过Heroku的开发者,或者有静态博客的朋友都能感受到一点——把版本控制与部署方案融合到一起非常方便。幸运的是,Capistrano对包括Git在内的各类版本控制有非常好的支持。本文中,我将使用Git作为版本控制软件,与Capistrano一起工作,进行项目部署。

如何部署?

利用Capistrano部署Rails程序,可以分为下面四个步骤。

  • 配置部署服务器
  • 对应用程序进行版本控制
  • 远程部署应用程序
  • 版本控制推进部署

配置部署服务器

对生产服务器的基本配置,包括Web静态服务器、数据库、版本控制搭建、防火墙等的控制不在本文讨论范围内。它们之中任何一点拿出来都够写一本书了。

首先,要在部署服务器可以访问到的地方创建一个新的版本库。

读者可以在公司/实验室里搭建GitLab,或者连接到GitHub上。如果是自己搭建GitLab,其实完全可以把Git服务器和生产服务器放在同一台机器上。可以通过以下命建立Server端的远程版本库,也可以通过访问Git服务器的Web界面自行操作。

1
2
3
$ mkdir -p ~/git/project.git
$ cd ~/git/project.git
$ git --bare init

值得注意的是,即使是把Git Server和Web Server放在同一台机器上,Capistrano也是通过Web服务的形式访问Git。这里可以配置公钥来简化整个流程。

1
2
$ test -e ~/.ssh/id_dsa.pub || ssh-keygen -t dsa
$ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys

还有一件非常重要的事情:Capistrano将在应用程序目录名和Rails子目录中插入名为current的目录,其中包括public子目录。在用Capistrano部署好的项目中,目录结构类似下面的样子(current是当前部署的版本,releases是该分支下根据版本生成的曾经的项目,shared中是各个版本共享的资源):

1
2
$ ls project
> current releases shared

而这个public目录就是我们熟悉的Rails程序中静态资源目录;也就是说,不论你用Apache或Ngnix还是其他Web服务器来部署静态资源,需要把这个目录设置为根目录。以Apache配置为例:

1
DocumentRoot /home/project/current/public/

到此为止,对服务器的预先配置就已经完成了,接下来的工作都可以在开发环境中完成。

对应用进行版本控制

最开始,要在项目的Gemfile中加入Capistrano gem:

1
2
3
...
gem 'capistrano'
...

然后执行命令bundle install来安装gem。接下来执行一条很重要的命令,它的作用是把项目中用到的gem及其版本号都记录下来:

1
2
3
4
5
6
$ bundle pack
//然后可以做一个版本记录,并推送到远程库
$ git add .
$ git commit -m "install capistrano & bundle gems"
$ git push origin master

以上,已经完成了项目gem整理。接下来我们要把项目代码放入生产环境。

远程部署应用程序

接下来的过程,我们可以先猜测一下:

  • 把代码pull到服务器的DocumentRoot
  • 在生产服务器上生成数据库
  • 安装gem
  • 重启Passenger
  • ……

这些事情,可以想到的话,就可以手动来做;但是等下,要Capistrano是做什么的……
没错,到了这一步,就可以显示Capistrano的威力了:自动化部署。以上的事情可以全交给它来做,当然前提是要写一份自动化部署的脚本。

首先,在开发环境的项目根目录中执行命令:

1
2
3
4
5
6
7
$ capify
[add] writing './Capfile'
[add] writing './config/deploy.rb'
[done] capified!
// Capistrano3中使用下面的命令
$ cap install

现在多出来了两个文件:Capfiledeploy.rb,前者是Capistrano对Rakefile的模拟,不需要改动,后者是一个自动化的脚本,需要编辑的就是这个。这个文件里需要用到一些Capistrano的DSL,可以看这里参考。在此给出一份比较简单的脚本作为参考,它是上面命令生成的默认脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# config valid only for Capistrano 3.1
lock '3.1.0'
set :application, 'my_app_name'
set :repo_url, 'git@example.com:me/my_repo.git'
namespace :deploy do
desc 'Restart application'
task :restart do
on roles(:app), in: :sequence, wait: 5 do
# Your restart mechanism here, for example:
# execute :touch, release_path.join('tmp/restart.txt')
end
end
after :publishing, :restart
after :restart, :clear_cache do
on roles(:web), in: :groups, limit: 3, wait: 10 do
# Here we can do anything such as:
# within release_path do
# execute :rake, 'cache:clear'
# end
end
end
end

在修改好:application:repo_url等值后,就可以开始进行部署了。
第一次部署的时候,请运行:

1
$ cap deploy:setup

之后会要求输入服务器密码。连接成功后会在生产服务器上生成必要的目录。

如果想测试配置,看还有没有别的问题,可以运行:

1
$ cap deploy:check

一旦解决完所有问题,就可以运行下面的命令,进行数据库生成,并完成部署:

1
2
$ cap deploy:migrate
$ cap deploy

至此,就已经把项目部署到生产服务器上了。

版本控制推进部署

已经部署完了么?

并不是这样的,不要忽视掉最开始强调版本控制的用意。Capistrano能让你在持续开发的情况下进行版本推进部署,而操作非常简单。每次做好提交、并把版本库推送到远端后,就可以运行cap deploy进行部署。

如果有某些原因,需要回到上一个部署的版本,执行命令:

1
$ cap deploy:rollback

这就完了?

没错!整个部署的过程就是这样。

如果想掌握关于它的高级用法,可以看Wiki文档。

本文只是以Rails为例讲解了Capistrano的用法,实际上它还可以用来部署其他语言写的Web应用程序,比如Java、PHP、Python等,读者有兴趣的话可以继续探索下去。