自动化部署工具 Capistrano 与 Mina - V2EX
fir.im Rio
fir.im 平台更新日志
快速获取 UDID
1 - 3 分钟发布应用
同时支持 iOS 和 Android
灵活设置应用权限
实时查看应用动态消息
自定义显示历史版本
随时了解应用下载情况
如果你也喜欢简单快速又美观的工具平台,就用 fir.im 吧!
BugHD
Imshaha

自动化部署工具 Capistrano 与 Mina

  •  
  •   Imshaha Jan 15, 2015 7038 views
    This topic created in 4136 days ago, the information mentioned may be changed or developed.

    这篇文章是 FIR.im Ruby 工程师黄轩宇的分享,文章总结了他如何使用 CapistranoMina 进行自动化部署,欢迎大家阅读并讨论。


    Capistrano

    Capistrano(下文简称 Cap) 特别适合于 Rails 应用的自动化部署, 特别是 Cap3, 整合了很多与 Rails 相关自动部署的命令(可用 cap -T 查看).


    0. 服务器目录结构

    首先来看看经过多次部署后, 服务器会生成一个这样的目录结构

    ├── current -> /var/www/your_app/releases/20141201042659 ├── releases │ ├── 20141201032351 │ ├── 20141201042256 │ ├── 20141201042659 ├── repo │ ├── branches │ ├── hooks │ ├── info │ ├── objects │ └── refs └── shared ├── bin ├── bundle ├── config ├── log ├── public ├── tmp └── vendor 
    • current 是指当前版本, link 到 release 下的指定版本目录(默认为最新的 releases)

    • releases 每次部署都会产成一个目录存放项目源码, 目录个数由 :keep_releases 变量来控制

    • repo 项目的 .git 目录

    • shared 是项目中共享的内容, 不会随部署而改变


    1. 安装 Cap

    # Gemfile gem 'capistrano', '~> 3.2.0' gem 'capistrano-rails', '~> 1.1.0' gem 'capistrano-bundler', '~> 1.1.0' gem 'capistrano-rvm', '~> 0.1.0' gem 'capistrano3-unicorn', '~> 0.2.0' # Add this if you're using rbenv # gem 'capistrano-rbenv', '~> 2.0.0' 

    2. Cap install 生成相关部署文件

    $ bundle install 之后执行 $ bundle exec cap install, 会自动生成以下几个文件

    ├── Capfile # Cap 配置文件 ├── config │ ├── deploy │ │ ├── production.rb # 不同环境的部署配置 │ │ └── staging.rb │ └── deploy.rb # 公共变量 └── lib └── capistrano └── tasks # 一些自定义的 task 

    3. Capfile 文件

    Cap 的配置文件, 可按需求加载一些插件

    require 'capistrano/setup' # 加载 Cap 的 DSL require 'capistrano/deploy' # 加载 Cap 的 Workflow require 'capistrano/rvm' # 加载 RVM 相关配置 # require 'capistrano/rbenv' # 加载 Rbenv 相关配置 require 'capistrano/bundler' # 加载 Bundle, 以便完成 bundle install require 'capistrano/rails/assets' # 加载 Rails 的 js, css 文件预编译 require 'capistrano/rails/migrations' # 加载 Rails 的数据库自动迁移 require 'capistrano3/unicorn' # 加载 Unicorn 服务 Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r } 

    其中, require 'capistrano3/unicorn' 后, 会增加几个 Unicorn 的部署命令, 可在本地远程运行命令直接控制服务器 Unicorn 的服务

    cap unicorn:add_worker # 增加一个 Unicorn Worker cap unicorn:duplicate # Restart cap unicorn:legacy_restart # 传统方式 Restart, 使用 USR2 + QUIT cap unicorn:reload # Reload cap unicorn:remove_worker # 减少一个 Unicorn Worker cap unicorn:restart # 无缝 Restart, 使用 USR2 cap unicorn:start # 启动 Unicorn cap unicorn:stop # 关闭 Unicorn (QUIT) 

    4. config/deploy.rb 文件

    用来配置不同环境的一些公共变量

    # config valid only for Capistrano 3.1 lock '3.2.1' set :application, 'your app name' # 设置部署项目的名字 set :repo_url, '[email protectd]' # 设置项目的 git repo set :deploy_to, "/var/www/xxx" # 设置部署目录 set :deploy_user, 'deploy' # 设置部署时的用户 set :scm, :git set :format, :pretty set :pty, true # linked_dirs # 是将项目的指定目录 link 到 shared 目录中, 这个操作会在从 repo 取下代码之后进行. # 比如 log 目录, 每次部署完毕后新的版本中的 log 目录都会 link 到 shared/log 下 set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system} # linked_files # 它是将 shared 目录中的文件 link 到项目中, 文件要首先存在于 shared 目录中, 不然 deploy 时会报错 # 在 Rails 项目中, 主要就是 database.yml, secret.yml 这样的敏感文件 set :linked_files, %w{config/database.yml} # rvm_type # :auto (default): just tries to find the correct path. ~/.rvm wins over /usr/local/rvm # :system: defines the RVM path to /usr/local/rvm # :user: defines the RVM path to ~/.rvm set :rvm_type, :system set :rvm_ruby_version, '2.1.2' set :rvm_roles, [:app, :web, :db] set :keep_releases, 10 # 最多存放十个部署版本 namespace :deploy do # 自定义了一个部署任务, 即自动运行 rake RAILS_ENV=rails_env db:create # 其中 release_path 指的是当前 release 目录 # `fetch(:rails_env)` 读取配置中的 rails_env 变量, 并在 rake 命令中带上 env 变量 task :create_database do on roles(:db) do within release_path do with rails_env: fetch(:rails_env) do execute :rake, 'db:create' end end end end before :migrate, :create_database # 在每次 rake db:migrate 前都运行 rake db:create after :finishing, 'deploy:cleanup' # 在每次部署完毕后, 清理部署时生成的 tmp 文件及多余的版本 end 

    这里有几个细节需要特别注意:

    • deploy_user 一定需要有 /var/www/[deploy_to] 的权限, 在自动化部署中, 部署者的权限是个很重要的因素!

    • deploy_user 建议使用 id_rsa.pub authorized_keys 的方式进行免密码登陆, 这也是 cap3 中推荐的方法

    • 首次部署, 需要执行 cap [environment] deploy:check 命令, 把 linked_files 在服务器上创建!

    • 首次部署, 如果用 Mysql 的话, 服务器上是没有 database 的, 需要自己手动 rake db:create, 这里我写了个 create_database 的 task 来执行 rake db:create

    • rvm 与 rbenv 的安装路径一定要确认, 是在 root 下安装的还是在 deploy_user 下安装的, 这里强烈建议用 deploy_user 安装 rvm/rbenv, 并且把 /var/www 文件夹的权限赋予 deploy_user, 这样会少走很多弯路


    5. config/deploy/production.rb | staging.rb

    Cap 中的运行环境(又称 Stage ), 默认建立了2个 Stage, 不同的 Stage 可以定义一些专有的变量, 并可以重写 deploy.rb 中定义的公共变量, 相当于不同环境下对应不同的服务器.

    # Production Stage set :stage, :production # 设置 stage set :branch, 'master' # 设置 git branch set :rails_env, :production # 设置 rails_env # 以下几个 server 会同时部署 server 'xxx.xxx.xxx.xxx', user: 'deploy', roles: %w(web app db), primary: true server 'xxx.xxx.xxx.xxx', user: 'deploy', roles: %w(web app db) 

    这里需要说明的是 roles 的定义, 在 Cap 中, 不同的 server 是可以有不同的 role 的, 一些服务器负责 web 服务, 一些服务器负责 db 服务, 从上面的自定义 create_database 命令中, 可以看到, on roles(:db), 说明这条命令只有在指定了 role 为 db 的服务器上运行.

    这里讲的是多台服务器同时部署, 那么如何实现多台服务器依次部署呢? 只要再写一个 Stage, 运行指定的 stage 就可以了


    6. Cap Flow

    部署的时候执行命令, cap [environment] deploy, Cap 会自动执行一系列 Task, 这些 Task 被称为 Cap Flow, 每个 Task 都可以通过 beforeafter 来添加自定义的 Task.

    deploy deploy:starting [before] deploy:ensure_stage deploy:set_shared_assets deploy:check # 检查 ssh, rvm/rbenv, linked_dirs, linked_files, git deploy:started deploy:updating git:create_release deploy:symlink:shared deploy:updated [before] deploy:bundle # 重新 bundle install [after] deploy:migrate # rake db:migrate deploy:compile_assets deploy:normalize_assets deploy:publishing deploy:symlink:release deploy:restart # restart, 可自定义一些需要 restart 的服务 deploy:published deploy:finishing deploy:cleanup deploy:finished deploy:log_revision 

    7. Cap stage deploy

    最后 show 一张运行 cap [environment] deploy 命令部署成功后的图片

    <img src="/images/deploy.png" alt="Capistrano Deploy">


    Mina


    Mina 相对于 Cap 来说, 较为简洁, 只有基本的几个 Task(可用 mina -T 查看), 有点 Sinatra VS Rails 的感觉, 其服务器部署结构与 Cap 类似.


    1. 安装 Mina

    # Gemfile gem 'mina', '~> 0.3' 

    2. Mina init

    $ bundle install 之后执行 $ mina init, 会生成 config/deploy.rb 文件, 定义了一系列的变量和 Task.

    require 'mina/bundler' require 'mina/rails' require 'mina/git' # require 'mina/rbenv' # for rbenv support. (http://rbenv.org) # require 'mina/rvm' # for rvm support. (http://rvm.io) # Basic settings: # domain - The hostname to SSH to. # deploy_to - Path to deploy into. # repository - Git repo to clone from. (needed by mina/git) # branch - Branch name to deploy. (needed by mina/git) set :domain, 'foobar.com' set :deploy_to, '/var/www/foobar.com' set :repository, 'git://...' set :branch, 'master' # Manually create these paths in shared/ (eg: shared/config/database.yml) in your server. # They will be linked in the 'deploy:link_shared_paths' step. set :shared_paths, ['config/database.yml', 'log'] # Optional settings: # set :user, 'foobar' # Username in the server to SSH to. # set :port, '30000' # SSH port number. # This task is the environment that is loaded for most commands, such as # `mina deploy` or `mina rake`. task :environment do # If you're using rbenv, use this to load the rbenv environment. # Be sure to commit your .rbenv-version to your repository. # invoke :'rbenv:load' # For those using RVM, use this to load an RVM version@gemset. # invoke :'rvm:use[ruby-1.9.3-p125@default]' end # Put any custom mkdir's in here for when `mina setup` is ran. # For Rails apps, we'll make some of the shared paths that are shared between # all releases. task :setup => :environment do queue! %[mkdir -p "#{deploy_to}/shared/log"] queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/log"] queue! %[mkdir -p "#{deploy_to}/shared/config"] queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/config"] queue! %[touch "#{deploy_to}/shared/config/database.yml"] queue %[echo "-----> Be sure to edit 'shared/config/database.yml'."] end desc "Deploys the current version to the server." task :deploy => :environment do deploy do # Put things that will set up an empty directory into a fully set-up # instance of your project. invoke :'git:clone' invoke :'deploy:link_shared_paths' invoke :'bundle:install' invoke :'rails:db_migrate' invoke :'rails:assets_precompile' to :launch do queue "touch #{deploy_to}/tmp/restart.txt" end end end # For help in making your deploy script, see the Mina documentation: # # - http://nadarei.co/mina # - http://nadarei.co/mina/tasks # - http://nadarei.co/mina/settings # - http://nadarei.co/mina/helpers 

    3. Mina setup

    部署的前执行命令, mina setup, 创建 shared 文件夹, 在编辑需要 shared 的文件后, 再执行 mina deploy 就可以部署了, 非常的简洁.


    REF

    Capistrano 3 实现Rails自动化部署

    Capistrano 3 Tutorial

    Mina For Deployment

    26 replies    2017-12-28 10:32:57 +08:00
    est
        1
    est  
       Jan 15, 2015
    用mina中。通过环境变量指定部署哪个机器。

    mina deploy to=prod

    在config.rb里需要处理下 if ENV['to'] == 'prod' set :domain, 'prod.xxx.com' end 这样。
    Imshaha
        2
    Imshaha  
    OP
       Jan 15, 2015
    中间有张部署成功图片是这样的:(image)[http://blog.naixspirit.com/images/deploy.png]
    Imshaha
        3
    Imshaha  
    OP
       Jan 15, 2015
    不好意思,markdown 语法不熟练 T-T, 应该是这个:![img](http://blog.naixspirit.com/images/deploy.png)
    Imshaha
        4
    Imshaha  
    OP
       Jan 15, 2015
    泪奔,原来评论不支持。。。
    blacktulip
        5
    blacktulip  
       Jan 15, 2015 via iPhone
    @Imshaha 传 imgur,然后贴图片直链地址
    sennes
        6
    sennes  
       Jan 15, 2015
    用markdown发的主题看起来真的很舒服!
    lovewilliam
        7
    lovewilliam  
       Jan 15, 2015
    每次看到楼主头像都点进来看看
    Travis
        8
    Travis  
       Jan 15, 2015 via iPhone
    @Imshaha 我是来看楼主评论里秀markdown语法排列组合的
    x3byg9oyv27Wlx
        9
    x3byg9oyv27Wlx  
       Jan 15, 2015
    同7楼
    GuBonjour
        10
    GuBonjour  
       Jan 15, 2015
    @Imshaha 默默地过来看楼主秀Markdown技能的 XD
    dishonest
        11
    dishonest  
       Jan 15, 2015
    一直觉得capistrano 太复杂,耦合又深。

    如果rbenv等工具版本更新 那是不是cap也要跟着更新

    用Fabric直接run command,会不会更灵活点?
    naixspirit
        12
    naixspirit  
       Jan 15, 2015
    @dishonest rbenv/rvm 等工具版本更新后, cap 是不需要更新的, 使用 cap 的好处是, 它的 flow 已经集成了大部分 Rails 所需要的东西, 而且 github 上还有大量的插件, 可以跟 Rails 紧密的结合了起来. 事实上, 我们用 nodejs 开发的项目也用上了 cap.
    Imshaha
        13
    Imshaha  
    OP
       Jan 15, 2015
    @GuBonjour
    @Travis
    你们这样真的好么,我会好好练习的,掩面泪奔。
    Imshaha
        14
    Imshaha  
    OP
       Jan 15, 2015
    @lovewilliam
    @bittenbydog 好吧,头像是有美白处理过的,哈哈。言归正传,这真的是一篇严肃认真的技术分享文章,好么:D
    Imshaha
        15
    Imshaha  
    OP
       Jan 15, 2015
    @sennes 还在熟悉Markdown语法过程中~
    guoer
        16
    guoer  
       Jan 15, 2015
    看头像进来的
    不是说不准全文转载吗?
    Imshaha
        18
    Imshaha  
    OP
       Jan 15, 2015
    @blacktulip 谢谢指导,原谅我没有仔细看 FAQ
    Imshaha
        19
    Imshaha  
    OP
       Jan 15, 2015
    @guoer 因为是我们团队工程师写的,并放在公司子节点而不是其他节点,所以是OK的啦~
    guoer
        20
    guoer  
       Jan 15, 2015
    @Imshaha 原来如此
    那姐姐约吗 XD
    Imshaha
        21
    Imshaha  
    OP
       Jan 15, 2015
    @guoer 。。。早点休息,小盆友
    redf
        22
    redf  
       Jan 15, 2015
    我可以证明,lz 确实很白
    Imshaha
        23
    Imshaha  
    OP
       Jan 16, 2015
    @redf 求不黑 T-T
    GuBonjour
        24
    GuBonjour  
       Jan 16, 2015 via iPhone
    @guoer 2333333 那姐姐约吗
    dishonest
        25
    dishonest  
       Jan 16, 2015
    @naixspirit 功能好是好, 总觉得ruby社区做的好多太复杂的东西了.

    我自己研究ror很久了, 之前很热衷用各种神奇的库, 单测试就数种高大上的工具, 后来发现好像搞复杂了. =.=b

    然后我就回python了 哈哈
    spkinger
        26
    spkinger  
       Dec 28, 2017
    这文档很有用,刚搜到的=。=,攒下
    About     Help     Advertise     Blog     API     FAQ     Solana     5842 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 221ms UTC 01:56 PVG 09:56 LAX 18:56 JFK 21:56
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86