$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

「capistrano設定の共通化(+ Tips集)」についてKyoto.rbで発表してきました

Kyoto.rbがあったので、Rubyのことはよくわからないながら、capistranoの話をして来ました。設定の共通化についてと、思いついたTips集を発表して来ました。サンプルはhttps://github.com/shibayu36/capistrano-deploy-sampleにおいてあります。

capistranoとは

  • デプロイ用ツール
  • コマンド一つでアプリケーションのデプロイが出来たりする
  • 特にRailsに特化してる

capistrano設定を社内などで共通化したい

  • 共通化しないとprojectごとでdeploy方法が違って死ねる
  • とはいえ一つのファイルで管理していると破綻する

最近の共通化の方針

  • やりたいことごとにファイルを作って共通化する
    • default設定, deploy用, cron, perlbrew, rbenv, daemontools, etc...
  • それぞれのサービスは必要な物だけloadし、必要な設定をset
  • サービスの差異を吸収しながら共通化できる
  • task名とその内容の標準化は別途必要

例など

https://github.com/shibayu36/capistrano-deploy-sample にデモで使ったサンプルを置きました。

構成はこんな感じ。

.
├── Capfile # サービスごとの設定
└── config
    ├── cron.rb        # cron設定
    ├── daemontools.rb # svc操作用関数
    ├── default.rb     # 共通deploy設定
    ├── perlbrew.rb    # perlbrew用
    └── utils.rb       # その他便利関数
  • config/以下に共通設定を格納しておく
  • Capfileで必要なものだけloadし、setを利用して設定する。

こういう感じに読み込んでおいて

load 'config/default' # repositoryの設定とかdeployの設定とか
load 'config/daemontools' # daemontoolsのsvcとか
load 'config/cron' # cronのupdateとか
load 'config/perlbrew'
load 'deploy'

こういう感じにCapfileでアプリケーション固有の設定をする

  set :crontab_path,         'config/crontab'
  set :crontab_install_name, 'deploy-sample.devel'

やりたいことごとに設定ファイルを細かく分けることにより、サービスごとに必要な物だけloadするようにできる。設定のコンフリクトも防げる。

Tips集

plugin編

deploy編

以下が協調して動作する

  • 本体のdeploy.rb
  • deploy/scm,
  • deploy/strategy

scm : version管理ツールの種類ごとのdeploy設定
strategy : どのようなdeploy方法をとるか

gitの設定

こんなかんじでやると良い。

set :scm, :git # git使う
set :git_shallow_clone, 1 # depth=1でやってくれる
set :git_enable_submodules, 1 # submoduleも

set :branch, "master"

set :repository do
  "git@host:projects/Hoge.git"
end
strategyの設定

deploy_viaを設定すればstrategyを決められ、様々な方法を選択できる。現状だと

  • checkout
    • remoteでcloneしてcheckout
  • copy
    • 手元からupload
  • remote_cache
    • cached-copy dirにclone
    • それをcpでコピーしてdeploy
    • 速い
set :deploy_via, :remote_cache

環境ごとに設定を変える

capistrano-extか動的role生成のどちらか。

  • capistrano-ext
    • production.rbとかstaging.rbとか作ると環境を切り分けてくれる
  • 動的role生成
    • taskでroleを動的に決めてあげる
task '@production' do
  role :app, 'production01.host'
  role :cron, 'production01.host'
end

task '@development' do
  role :app, 'development01.host'
  role :cron, 'development01.host'
end

以下のように実行。

cap @production deploy # 本番へdeploy
cap @development deploy # 開発用へdeploy

task実行サーバの制限

roleの制限

role :app, 'app.host'
role :db,  'db.host'
task :restart, :roles => [:app] do
  ...
end

onlyでの制限

role :app, 'app.host', :perl => true
role :db, 'db.host'
task :perl_setup, :only => { :perl => true } do
  ...
end

defaultタスク

  • defaultというタスクを作っておく
  • するとnamespaceでタスクを呼べる
namespace :deploy do
  task :default do
    update
    restart
  end
  task :update do
    ...
  end
  task :restart do
    ...
  end
end
cap deploy # => cap deploy:update deploy:restart

質疑応答などで答えたりしたこと

覚えている限りで

  • cap shell便利です
  • cap -Tみたいなのあるけどそれでも一ファイルだとわけわからなくなる?
    • 特に設定が微妙に衝突することのほうがまずいので、分けた方がよさそう
  • taskの継承とか出来るの?
    • 継承という概念は無いけどbefore afterでhookかけられる
before "hoge" do
  run "echo 'run command'"
end

task 'hoge' do
  run "ls"
end
  • runに:shellを渡すとどういうshellで実行するか決められる
task 'perl_version' do 
  run "perl -v", :shell => "PERLBREW_HOME=#{perlbrew_root}/.perlbrew . #{perlbrew_root}/perl5/perlbrew/etc/bashrc && perlbrew use #{perlbrew_perl_version} && sh"
end