fabric を使って、capistranoのdeploy.rb風のデプロイをする
今やってるプロジェクト(Web アプリケーションフレームワークは、CakePHP2)で、デプロイの方法をどうしようかと色々悩んだ結果、fabricというのを使ってみた。
Welcome to Fabric! ? Fabric documentation
元々rails用のデプロイツールであるcapistranoを使ってた(その時もWeb アプリはperlだったりphpだったりしたけど、デプロイのためにrubyをインストールしてた)ので、capistranoのようなデプロイを、fabricでもやりたい。
### デプロイで満たしたいこと ###
– 動作環境のセットアップができる
– 複数の環境にデプロイできる
– マイグレーションと統合されている
– ソースコードの取得からWebサーバの再起動までがワンコマンドで完了する
という感じなのだけど、fabricでは特に、deploy.rbに相当するようなものは提供されていない様子。
capistranoのdeploy.rbが何をやっているかを知らないといけないけど、結構考えられていて複雑だったりするので、
だいぶ日和って以下のことだけするfabfile.pyを用意した。
+ セットアップ: サーバ上の動作ディレクトリを作成する。
+ ソース準備: リポジトリからソースを取得してtarで固めて、サーバに送る。
+ リリース作成: releases ディレクトリに配置してシンボリックリンクなどを貼る。
+ マイグレーション: 適応してないマイグレーションがあれば適応する。
+ リリース: currentのリンク先を作成したreleasesに変更する。
+ サーバ再起動: apache再起動
簡単にするため、毎回上記の処理を行なうようにした。
TODO: リビジョンを指定してデプロイができるようにする。
用意したfabfile.pyです。
### fabfile.py ###
# -*- coding: utf-8 -*- import time from fabric.api import run, local, cd, lcd, env, sudo, put app_dir = '/var/vhosts/hoge' shares = ['webapp/app/tmp'] version = time.time() version_dir = '%s/releases/%s' % (app_dir, version) cake_env = '' # ENV # env.use_ssh_config = True def staging(): global cake_env cake_env = 'staging' env.hosts = ['hoge-staging-web'] def production(): global cake_env cake_env = 'prod' env.hosts = ['hoge-prod-web'] # tasks # def directory_setup(): """ 自動デプロイのためのディレクトリ構成を作成する """ sudo('mkdir -p %s' % app_dir, shell=False) sudo('chown %s:%s %s' % (env.user, env.user, app_dir), shell=False) run('mkdir -p %s/{releases,shared}' % app_dir) with cd('%s/shared' % app_dir): for d in shares: run('mkdir -p %s' % d) def prepare_files(): """ ローカルでsvnからソースを取得し、tarで固めてから、scpでサーバに転送する。 """ tmp_dir = '/tmp/%s' % version package_file = '/tmp/%s.tar.gz' % version local('mkdir %s' % tmp_dir) with lcd(tmp_dir): local('svn export https://svn.hoge.jp/hoge/trunk/src/webapp > /dev/null') with lcd('/tmp'): local('tar zcf %s %s' % (package_file, version)) local('rm -rf %s' % version) put(package_file, '/tmp') return package_file def create_release(package_file): """ ソースをサーバ上のリリースファイル用ディレクトリに格納する。 """ with cd('/var/vhosts/hoge/releases'): run('tar zxf %s' % package_file) run('rm %s' % package_file) def symlink_shared(): """ 各バージョンで共有すべきディレクトリをシンボリックリンクで復元する。 """ for d in shares: run('rm -rf %s/%s' % (version_dir, d)) run('ln -s %s/shared/%s %s/%s' % (app_dir, d, version_dir, d)) sudo('chown -R apache:apache %s/shared/%s' % (app_dir, d), shell=False) sudo('chmod -R 777 %s/shared/%s' % (app_dir, d), shell=False) def migrate(): """ DBのマイグレーションを実行する。 """ with cd(version_dir): run('CAKE_ENV=%s webapp/app/Console/cake Migrations.migration run all -p' % cake_env) def symlink_release(): """ currentのシンボリックリンクを貼り替えて、新バージョンを公開する。 """ with cd(app_dir): run('rm -f current && ln -s %s current' % version_dir) def restart(): """ apacheの再起動 """ sudo('/etc/init.d/httpd restart', shell=False) def deploy(): directory_setup() package_file = prepare_files() create_release(package_file) symlink_shared() migrate() symlink_release() restart() # vim:set ts=8 sts=2 sw=2 tw=0: |
## まとめ ##
fabric が、pythonのコードで記述できるから、アクロバチックなこともやろうと思えばできるという安心感もありつつ、元がシンプルだから更に良いです。
fabricを気に入ると同時に、capistranoのdeploy.rbは優れたものだなと再認識した。deploy.rbは、rails文化が生んだデプロイの概念が形になったものなんだろうな。(rails触ったことないけど)