402v /posts/railskai-fa-huan-jing-capistrano-3shi-xian-railszi-dong-hua-bu-shu
Rails开发指南 - Capistrano 3实现Rails自动化部署
From Where: Rails开发指南 - Nginx+Unicorn的服务器配置
我们之所以使用rails的就是为了简单方便,于是就少不了自动化发布我们的项目,配置之后只要每次运行
cap deploy就可以把本地开发的项目发布到服务器上,没有任何多余的操作而且是zero downtime的!
#基于Capistrano自动发布(Deploy)
Rails自动化发布通常有可以有两个不同的gem来实现,本文所讲的Capistrano是其中之一,另外一个mina算是较轻量级的deploy库,使用也很广泛,配置的方式与cap3比起来也是大同小异。
###Capistrano初始化 首先在gem中添加Capistrano相关的gems,因为除了cap的gem外,cap的官网上还提供了一些插件用于控制bundler、rails、rbenv等等。
group :development do
# Use Capistrano for deployment
gem 'capistrano', '~> 3.1.0'
# rails specific capistrano funcitons
gem 'capistrano-rails', '~> 1.0.0'
# integrate bundler with capistrano
gem 'capistrano-bundler'
# if you are using RBENV
gem 'capistrano-rbenv', "~> 2.0"
end
运行bundle install安装gems;
然后运行bundle exec cap install初始化capistrano的环境,会创建这样几个文件:

我们一个一个来解释:
-
deploy.rb是最主要的一个,运行cap deploy时的主要配置都在这里; -
Capistrano有stage的概念,类似于rails的environments,默认有两个starge:staging和production。因此新版的cap运行deploy时需要指定stage:
cap production deploy,后面会讲到如何指定一个默认的stage。deploy/staging.rb、deploy/production.rb两个文件就是在运行不同stage时特定配置的指定文件,有区别的配置放在这里,各个stages通用的配置尽量放在deploy.rb; -
lib/capistrano/tasks:之前提到lib文件夹时已经说过这个文件夹主要存放默写gem用到的资源和rake文件。Capistrano3整体迁移到rake上来,所以cap3的task编写基本和rake文件一样。 -
除此之外还要介绍一个与
Gemfile统计目录下的Capfile,这个文件主要是用来为cap模块载入需要的.cap文件和.rb文件。根据需要require对应的插件,Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r }这一句将tasks路径下的task文件都加载进来。当然还可以增加Dir.glob('lib/capistrano/tasks/*.rb').each { |r| import r }这样一行load所有的.rb文件。根据我们接下来需要的配置和已引入的插件gems,我们会开启下列几个require:require 'capistrano/rails' require 'capistrano/rbenv' require 'capistrano/bundler' require 'capistrano/rails/assets'
###Deploy文件配置 deploy文件分为两个主要部分:
- 参数配置部分(多数以set方法开头,设置各种各样的环境变量);
- task部分,默认只有deploy这一个namespace。
deploy文件(或者说Capistrano部署)的核心是deploy这个namespace下的task,Cap3在deploy的时候会按照一定的次序运行这些task来完成工作。
- 如果想要git update之后执行bundle install,需要rbenv和bundler两个plugin;
/usr/bin/env bundlenot found 问题的解决办法,原因是cap默认使用non-login, non-interactive shell,这幅图解释了shell启动时加载环境变量的过程。- app_name & git repo etc.
- default stage
- deploy_to: /var/www/app_name 需要root权限,可以发布到
/home/#{fetch(:deploy_user)/apps/app_name下 - linked_files & linked_dirs: 影响其他配置,如nginx、unicorn
- database.yml,
-
如果现在deploy会报错:
ERROR linked file /home/deploy/apps/projects/shared/config/database.yml does not exist on server.com,因为database.yml文件内配置的是数据库用户名密码等私密信息,因此不能通过放到git库中同步到server。 -
原因如Capistrano官方所说敏感文件一定要在本地ignore掉,ignore这步
rails new的时候已经做了; -
最正确的处理办法是通过scp把database.yml文件拷贝到server上:
scp config/database.yml deploy@oneboxapp.com:/home/deploy/apps/projects/shared/config/database.yml -
这里还有一些关于database.yml等敏感文件处理的办法。
-
自动化task的做法是新建setup task然后在udpated工作流之后运行它:
task :setup do sh "scp config/database.yml deploy@oneboxapp.com:/home/deploy/apps/projects/shared/config/database.yml" end
-
- deploy成功,根据我们之前的配置,80端口收到的网络请求是通过nginx转发给unicorn的,此时需要重启之前配置好的
unicorn_projects服务: assets:precompile,找不到database.yml的解决办法:
###需要自动化的部分
- git clone之后bundle install
- database.yml拷贝
- unicorn init程序
- nginx网站配置
- unicorn重启
- nginx重启
之前每次配置deploy.rb文件都是从网上down一份,没有仔细研究,所以这次手打了一份,从最基础的参数配置和task编写开始,因此中间也遇到一些比较初级的问题,希望对遇到这些问题的人有所帮助。
-
deploy unicorn:
- 遇到一个问题:无论如何deploy,production页面的assets MD5也不会改变。问题的原因是deploy的过程中没有重启unicorn,而unicorn在执行过程中会把整个rails
?缓存下来,因此无论如何生成都会展示老页面。
- 遇到一个问题:无论如何deploy,production页面的assets MD5也不会改变。问题的原因是deploy的过程中没有重启unicorn,而unicorn在执行过程中会把整个rails
-
asset-pipeline配置:(fingerprint,production,pre-compile)
###deploy tasks
-
unicorn的重新启动,配置文件如下:
#!/bin/sh ### BEGIN INIT INFO # Provides: unicorn # Required-Start: $all # Required-Stop: $all # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: starts the unicorn app server # Description: starts unicorn using start-stop-daemon ### END INIT INFO set -e USAGE="Usage: $0 <start|stop|restart|upgrade|rotate|force-stop>" # app settings USER="deploy" APP_NAME="projects" APP_ROOT="/home/$USER/apps/$APP_NAME/current" ENV="production" # environment settings PATH="/home/$USER/.rbenv/shims:/home/$USER/.rbenv/bin:$PATH" # -su: bundle: command not found CMD="cd $APP_ROOT && /home/$USER/.rbenv/shims/bundle exec unicorn -c config/unicorn.rb -E $ENV -D" PID="$APP_ROOT/tmp/pids/unicorn.$APP_NAME.pid" OLD_PID="$PID.oldbin" # make sure the app exists cd $APP_ROOT || exit 1 sig () { test -s "$PID" && kill -$1 `cat $PID` } oldsig () { test -s $OLD_PID && kill -$1 `cat $OLD_PID` } case $1 in start) sig 0 && echo >&2 "Already running" && exit 0 echo "Starting $APP_NAME" su - $USER -c "$CMD" ;; stop) echo "Stopping $APP_NAME" sig QUIT && exit 0 echo >&2 "Not running" ;; force-stop) echo "Force stopping $APP_NAME" sig TERM && exit 0 echo >&2 "Not running" ;; restart|reload|upgrade) sig USR2 && echo "reloaded $APP_NAME" && exit 0 echo >&2 "Couldn't reload, starting '$CMD' instead" $CMD ;; rotate) sig USR1 && echo rotated logs OK && exit 0 echo >&2 "Couldn't rotate logs" && exit 1 ;; *) echo >&2 $USAGE exit 1 ;; esac
可以用两种方式:
* 保存一个shell文件放在/etc/init.d下,每次通过service重启这个服务。
sudo chmod 755 /etc/init.d/unicorn_appname
sudo update-rc.d unicorn_appname defaults
通过下面这条命令重启
sudo service unicorn_appname start
* 另一种方式是将shell文件放在github库里面,通过capistrano的deploy命令触发它。
# in deploy.rb
set(:executable_config_files, %w(
unicorn_init.sh
))
# in some setup cap
executable_files = fetch(:executable_config_files)
executable_files.each do |file|
execute :chmod, "+x #{shared_path}/config/#{file}"
end
`#{shared_path}/config/#{file}`即为unicorn启动shell文件的路径。
###Stage文件配置及默认Stage
Staging的概念可以看官方文档,如果不配置默认stage,每次运行是必须指定,比如: cap production deploy这样,在Capfile中添加:
Rake::Task[:production].invoke
即可指定默认stage为production,可参见so上的回答。
#参考连接
Where to go: Rails开发指南 - 问题整理和常见命令
评论 · 0
还没有评论。