chroju.dev/blog

the world as code

Capistrano3がわからんので今一度イチから考えなおしてみる

前回Capistranoが上手くいかないというエントリーを上げてから1か月。いまだにハマってしまっている……。何が悪いの皆目検討もつかない、というほどではないのだが、なんというか、雲を掴んでいるような状態ではある。一旦Capistranoについて整理してみるべきなんだろう。

Capistranoは何をしてくれるのか

そもそもCapistranoとは何をしてくれるツールなのか?

Capistrano3のデプロイフレームワークの使い方 - Qiita

Capistranoは2まではRailsのデプロイツールだったけど、3は汎用的なデプロイツールに変わっている。したがってデフォルトの状態ではRails用のデプロイタスクは特に含まれていない。このあたりが上の方のリンク先で語られている内容になる。

ではデフォルトでのデプロイタスクは何をするのかと言えば、およそサーバーへのデプロイとして一般的に行われるようなものが組み込まれている。capistrano/lib/capistrano/tasksあたりを探るとデフォルトタスクがよくわかる。

  • releases、sharedなどディレクトリの作成
  • レポジトリからgit clone
  • linked_files、linked_dirsの存在確認とシンボリックリンク作成
  • currentディレクトリへのシンボリックリンク作成
  • 最古世代の削除、クリーンナップ

ざっくり見てしまうと、単純にサーバーへファイルを上げて自動的に世代管理をさせるだけであればこれだけでもなんとかなりそうなところではある。逆にこれらが煩わしいのであれば、デフォルトタスクを無効化して使う手もある。デフォルトタスクの内容がよくわからないのであれば、一旦無効化してすべて自分でタスクを書くというのも手だと思う。

Railsをデプロイする場合はこれだけでは足りないので、capistrano/railsやcapistrano/bundleを追加で読み込むことになる。

Capistranoのディレクトリ構成

Capistranoでデフォルトのデプロイを行った時、デプロイ先サーバーに作成されるディレクトリについてもよくわかってないのでまとめておく。deploy.rbのdeploy_toで指定したディレクトリ内に、次の3つのディレクトリが作られる。

  • releases : デプロイした内容を世代管理する
  • shared : bundleとかdatabase.ymlとかGitで管理してないファイル置き場(多分)
  • current : releasesの最新世代とsharedのシンボリックリンクが置かれる

基本的に「デプロイ」される先はreleasesだ。releases配下にはデプロイ時のタイムスタンプから生成された名前のフォルダが作られ、その中にごっそりデプロイしたファイルが入っている。タイムスタンプが付くということは当然世代管理されているわけだが、保持される世代数はdeploy.rbのset :keep_releasesで好きに指定できる。で、最新世代についてはcurrent配下にシンボリックリンクが自動的に貼られる。

sharedは正直よくわからない。デプロイのたびに更新するわけではない、すなわちGitで管理をしていないファイルやディレクトリを置いておくみたいなのだが、ではどうやって配置すれば良いのか?がわからない。配置したファイルのうち、必要なものについてはlinked_dirsとlinked_filesで指定すればcurrent配下にこれもまたシンボリックリンクが貼られる。しかし、どうやって配置すれば良いのかわからない。

関連:[自分用メモ]Capistrano3のlinked_filesって自分でuploadしなきゃダメですか? - Qiita

で、これを書いていて気付いたのだが、アプリの中身がcurrent配下に展開されるということは、ウェブサーバーの設定もdeploy_toではなくてcurrentに飛ばすようにしておかないといけないわけだ。俺だけかも知れんが、案外罠ではないかという気がする。

capistrano/rails

取りあえずsharedの話はほっといて、Railsをデプロイする話に戻る。冒頭でデフォルトタスクにはRailsに対するものは何もないと書いたが、それではRails用のデプロイタスクはどこで生成されているのか? 答えから書けば、capistrano-railsを読み込むことによって初めて生成される。

Capistrano3におけるRailsのデプロイタスクの内部実装 - Qiita いわく、追加されるタスクは主に3つ。

  • assets compile(deploy:compile_assets)
  • assetsのタイムスタンプ更新(deploy:normalize_assets)
  • db:migrate(deploy:migrate)

逆に言えば、ここで追加される以外のタスクはデフォルトでは行われないということになる。その点を配慮せずにただググって適当なdeploy.rbをコピーしたりしただけでは、思ったとおりのデプロイは出来ない。

一例として自分がハマったのが、db:createは行われないということ。schema.rbを使って初回デプロイのときに上手いこと云々なんてことは一切してくれないので、このあたりは自分で書くか、サーバーを作ったときに予めDBをこしらえておく必要がある。

capistrano/bundle

もうひとつ、RailsをCapistranoでデプロイする場合に必要なのがcapistrano/bundler。Rails使っててGemfileがないなんてことはないだろうし、というかcapistrano/railsの中で明示的にrequireされている。何をやっているのかと言えば、簡単な話しである。

  before 'deploy:updated', 'bundler:install'

デフォルトではshared配下にbundleディレクトリを作ってbundle installをかけてくれる。パスについてはset :bundle_pathオプションで自由に指定ができる。

capistrano/rbenv

あとよく使われるものとして、capistrano/rbenvがある。デプロイ先のサーバーで、Rubyをrbenvを使って入れてる場合には必須になるもの。中身はよく知らないが、そこまで気にしなくても良いのではないかという感覚がある。入れたらdeploy.rbにset :rbenv_ruby_versionで使うRubyのバージョンを指定すればOK。

同じ類のものとして、capistrano/rvmももちろんあります。

ソースにあたることの必要性

以上がCapistrano3でRailsをデプロイする場合の主なデフォルトタスクの内容になる。繰り返しになるが、これ以外に何をやりたいのならタスクは書く必要がある。よく言われるのがデプロイ後のウェブサーバーの再起動で、unicornを再起動するタスクを追加している例はよく見かける。ただ、これもcapistrano3-unicornという便利なものがすでに作られていたりはする。

個人的な思いなのだが、Capistrano公式の「Getting Started」は説明が不十分な気がしてならない。デプロイに至るまでの設定ファイルの書き方やら何やらは確かにだいたい載っているのだが、ではCapistrano3の内部実装がどうなっているのかとか、タスクを自分で書くにはどうすればよいのかといったあたりの情報が足りない。自分はまだこのDSLを読み下せないのだが、rakeあたりを知っていると結構書けるものなんだろうか? ひょっとしたら、自分のようなRubyやRails初心者が安易に手を出すものではないのかなぁとか思う。

ただ、GitHubにいずれもソースが上がっているので、根気よく読んでいけばCapistranoが何をしているのか、また何を求めているのかは理解できる。誰かの書いたノウハウに頼るより、ソースにあたるのが大切なのは基本だと思う。常に。