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/ が挟まっていないので場合分けして従来通り動くようにしておかないとギャッとなります。

もともと考慮していたもの

たぶんこの準備ができているといないとで大きく作業時間が変わってきます。

  1. 全部バージョン管理する
  2. できるだけ設定は php.ini から分離させているので、一つのサイトだけを独立して扱いやすくなってる
  3. .htaccess などはスクリプトから自動生成
  4. このスクリプトは自身の置き場所からもろもろのパスを自動解決

このため必要なことのほとんどは setup 用のスクリプトを絶対パスで動くようにすることでした。

1 が地味にハードル高いかもしれません。実は古いサイトは無駄にファイルが多すぎたり開発者と更新者で触るファイルが混ざっていたり、そもそもバージョン管理を作業者全員に教えるのが大変とか様々な理由でバージョン管理していない場合があります。

今回のサイトは「全部」バージョン管理されています。ただし全員が中央のリポジトリにcommitできる形ではない変則的な運用になりますが2

バージョン管理は必須と考えた方がいいと思います。安心して使えるファイル群がどれなのかが一意に決まるし、「いつの時点」も revision や commit hash で容易に特定できるからです。もちろん組織に馴染まない可能性はありますが。

DOCUMENT_ROOTからのsymlinkで公開する方法は使える

今回のサイトの公開はもともと symlink の生成で行われるので、この link が切り替わらない限り従来の方法で deploy したサイトは壊れないということが大きな安心に繋がりました3

実は symlink 生成での公開になったのは当時としては苦し紛れだったんですが、今回はこれがとても役に立ちました。

実はDOCUMENT_ROOT 以下に直接ファイル置かない方がいろいろ便利かもしれません。

独自セットアップスクリプトはいつ動かす

deploy:restart hook に定義しました。今回はサーバの再起動は必要ないものなので、再起動させずにセットアップ用のスクリプトを動かすだけです。

まとめ

CI のときも思ったけど、ちゃんと自動化しておいてよかった。

  1. Capfile やconfig/deploy.rb は手元のものが使われるため。 

  2. このため wtnabe は普段自分用に git-svn を使いつつ「共有」用に hg も使うというアホなことをしています。 

  3. このスクリプト作成時や公開当初に Capistrano の current -> releases/XXXXXX の link 方式を意識していたわけではありませんでした。 

More

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Develop Document Jekyll