PHPのサイトをcapistranoで自動deployしてみた
最近バックエンドのバックエンドの整備を進めています。今回は PHP でできたサイトを Capistrano で deploy できるようにしました。
構成
今回のサイトは Rails 風のディレクトリで言うと
...
sub/
app/
public/
setup_script*
DOC_ROOT/foo -> sub/publib
...
こんな感じになっていて、DOCUMENT_ROOT のツリーの外にある public/ への symlink を作成して、そこから app/ などのコードを読む、ちょっと変わった形の PHP 製の Web サイトです。
とても残念なことにオレフレームワークでできています。
準備
ruby と bundler gem は事前にインストールしておいてください。
上の sub/ に当たる手元のツリー上で
source :rubygems
gem 'capistrano'
- 上の内容の Gemfile を作って
- bundle install [–path vendor]
- bundle exec capify
- Capfile, config/deploy.rb の編集
- bundle exec cap deploy:setup
releases, shared というディレクトリがない限り、ここまでは従来サイトを壊さずに、かつ何もcommitせずに行えます1。
自分の場合は Capistrano そのものは他の Web サイトへの deploy や定型タスクの管理などに使っていたのでここでそれほど苦労はありませんでした。
できれば最初は Capistrano と相性のいいフレームワーク(Railsなど)で練習しておいた方がいいと思います。
setup 用のスクリプトは実際にサーバ上に展開されたあとに実行されるので、直しては commit して deploy、をくり返すことになります。ここで commit log がとても汚くなります。うぅ…。
今回の影響
上のツリーの中の
sub/
以下に直接 upload していたものが cap deploy:setup のおかげで
sub/
releases/
shared/
となり、sub/releases/ 以下への deploy になります。
従来は sub/ 以下で手作業で setup 用のスクリプトを叩いていたので、スクリプト内で自身からの相対パスでいろいろな作業をしていたんだけど、Capistrano から実行するには相対パスを絶対パスに直して実行する必要があります。
あとは releases/ が挟まっている場合とそうでない場合で DOC_ROOT がこのスクリプトから見て ../../ から ../../../../ にずれてしまうので、その対応をすれば ok となります。実際には実行するスクリプトが current/ 以下にあるので current が挟まっていると絶対パスを算出したときに 2階層ずれる、というパッと見分かりにくいコードになってしまいますが。
※ 開発環境などでは releases/ が挟まっていないので場合分けして従来通り動くようにしておかないとギャッとなります。
もともと考慮していたもの
たぶんこの準備ができているといないとで大きく作業時間が変わってきます。
- 全部バージョン管理する
- できるだけ設定は php.ini から分離させているので、一つのサイトだけを独立して扱いやすくなってる
- .htaccess などはスクリプトから自動生成
- このスクリプトは自身の置き場所からもろもろのパスを自動解決
このため必要なことのほとんどは setup 用のスクリプトを絶対パスで動くようにすることでした。
1 が地味にハードル高いかもしれません。実は古いサイトは無駄にファイルが多すぎたり開発者と更新者で触るファイルが混ざっていたり、そもそもバージョン管理を作業者全員に教えるのが大変とか様々な理由でバージョン管理していない場合があります。
今回のサイトは「全部」バージョン管理されています。ただし全員が中央のリポジトリにcommitできる形ではない変則的な運用になりますが2。
バージョン管理は必須と考えた方がいいと思います。安心して使えるファイル群がどれなのかが一意に決まるし、「いつの時点」も revision や commit hash で容易に特定できるからです。もちろん組織に馴染まない可能性はありますが。
DOCUMENT_ROOTからのsymlinkで公開する方法は使える
今回のサイトの公開はもともと symlink の生成で行われるので、この link が切り替わらない限り従来の方法で deploy したサイトは壊れないということが大きな安心に繋がりました3。
実は symlink 生成での公開になったのは当時としては苦し紛れだったんですが、今回はこれがとても役に立ちました。
実はDOCUMENT_ROOT 以下に直接ファイル置かない方がいろいろ便利かもしれません。
独自セットアップスクリプトはいつ動かす
deploy:restart hook に定義しました。今回はサーバの再起動は必要ないものなので、再起動させずにセットアップ用のスクリプトを動かすだけです。
まとめ
CI のときも思ったけど、ちゃんと自動化しておいてよかった。