スタートアップの最強最速デプロイシステム

タイトルは安定の釣りです(でも、半分は本当です)。

近年、マイクロサービスやSPA(シングル・ページ・アプリケーション)、JavaScriptフレームワークにDocker...と相変わらず新技術の話題が賑わっている訳ですが、99%のスタートアップは屍と化すことが前提であるが故これらの概念を必要とせず、スピード重視の開発がなされているのではないかと思います(良い意味でも悪い意味でも実はなされていない現場が多いのかもしれませんが)。

デプロイもその内の一つ。デプロイツールには代表格CapistranoPHP製Deployer他様々なものがありますが、git/SVNバージョン管理システムに依存していたり、導入するのに「俺、bundleとかGemfileとかいう言葉知らないしー(棒)」「設定ファイルとか勉強したくねー(棒)」といった煩雑さを嫌うニーズもあるかと思います。

かといって、scpでの個別ファイルアップやrsyncはいくらなんでもエンジニアとしてないよねという時に「漢は黙ってシェル書くんだよ!」ということで(ぇ
以下、自分が使っているものを公開いたします。

#!/bin/sh

# your setting
SSH_HOSTNAME=www.example.com
SSH_USERNAME=username
PROJECT=projectname
APP_ROOT=/var/www/${PROJECT}
DEPLOY_DST_DIR=/var/www/
LIMIT=30

FILE_PREFIX=${PROJECT}__
VERSION=`date +'%Y%m%d-%H%M%S'`

cd ${APP_ROOT}/.. &&
tar zcf /tmp/${PROJECT}.tar.gz $PROJECT &&
scp /tmp/${PROJECT}.tar.gz ${SSH_HOSTNAME}:/tmp &&
ssh ${SSH_USERNAME}@$SSH_HOSTNAME "cd /tmp && tar zxvf ${PROJECT}.tar.gz && mv $PROJECT $DEPLOY_DST_DIR$FILE_PREFIX$VERSION && ln -fsn $DEPLOY_DST_DIR$FILE_PREFIX$VERSION $APP_ROOT"

CNT=`ssh ${SSH_USERNAME}@$SSH_HOSTNAME "cd $DEPLOY_DST_DIR && ls -d ${FILE_PREFIX}* | wc -l"`

if test "$CNT" -ge $LIMIT ; then
    RM_NUM=`expr $CNT - $LIMIT`
    ssh $SSH_HOSTNAME "cd $DEPLOY_DST_DIR && ls -d ${FILE_PREFIX}* | sort | head -n $RM_NUM | xargs rm -rf "
fi

20行程度の凄い単純なコードですが、上から説明していきますね。

  • SSH_USERNAME:SSHユーザー名
  • SSH_HOSTNAME:デプロイ先SSHホスト名
  • PROJECT:開発中のプロジェクトディレクトリ名
  • APP_ROOT:開発中のプロジェクトまでのパス
  • DEPLOY_DST_DIR:デプロイ先ディレクトリのパス
  • LIMIT:デプロイ先で残すバージョン数
を設定します。

これで、デプロイ先ディレクトリ『/var/www』に『projectname__20160916-140748』といった形式でデプロイがされていきます(バージョン識別子はデプロイ日時から自動で生成しています)。新旧プロジェクトの切り替えはシンボリックリンク形式です。
Apacheであれば『Options FollowSymLinks』の設定をするなりしてあげて下さい。

以下、デプロイ先の状況です。最新のものにシンボリックが貼られ、それ以外のものは指定分バックアップとして残されます。

lrwxrwxrwx  1 username username   31  9月 22 08:08 2016 projectname -> /var/www/projectname__20160922-080839
drwxrwxr-x  9 username username 4096  9月 16 13:29 2016 projectname__20160916-140748
drwxrwxr-x  9 username username 4096  9月 16 13:29 2016 projectname__20160916-140930
drwxrwxr-x  9 username username 4096  9月 17 19:13 2016 projectname__20160922-075221
drwxrwxr-x  9 username username 4096  9月 17 19:13 2016 projectname__20160922-080408
drwxrwxr-x  9 username username 4096  9月 17 19:13 2016 projectname__20160922-080839

説明は以上です。

rmコマンドがあるプログラム故、私もテスト時にうっかり「ssh $HOSTNAME "cmd rm"」しないでcmd rmだけして、ローカルプロジェクト削除⇒リポジトリからリストアして事なき(汗)みたいなことをやっていたりと、シェルスクリプトの事、そして、シンボリックリンクのセキュリティについて知らないで使うととんでもない事になる恐れがありますので自己責任でお願いします

PHPで実現するRuby on Rails風味なAsset Pipelineフィンガープリンティング

5年ぶりのblogです。
以前のものは黒歴史を感じてプライベートモードにしましたw

さて、わたくし、PHP暦15年になるのですが、ここにきてPHPフレームワークに不満を感じる機会が多くなり、今年は初めてRuby on Railsに触れてみました。一人我流でWEBサービスを1個リリースした程度なので、本来のRailsを理解しているとは言い難いですが、そんな私から一つエントリーを。

Ruby on RailsのAsset Pipelineは最強ですが、その中の機能の一つにフィンガープリンティングがあります。

<link rel="stylesheet" href="/assets/style-f88b32d7f32262a8bb900c0df155644c351fa0bc5954a7f6235f40d252dc0e5d.css" />

こんな感じでファイル名に文字列を付加して、リクエストURIを変えることによりブラウザキャッシュ対策をする機能ですが、PHPフレームワークだと未だに、≪style.css?random≫なんて対応がされていて、萎えている人も多いのではないでしょうか。
ランダムパラメータ付加はブラウザによっては同一URIとみなされ、キャッシュ対策として機能しません。

やっぱRailsだよなー。所詮PHPerだもんなーなんて刹那に思ってしまったものの、よくよく考えてみるとアプリケーションサーバ型でないPHPで、これ実現するのって無理じゃね?って気付きました。愛しのPHPたんゴメンなさい!

PHPで実現する方法は以下。WEBサーバもいじる必要があります。

Apachehttpd.conf

AliasMatch ^/assets/css/(.*)(-version-[0-9]*).css$ /path/to/app/htdocs/assets/css/$1.css

PHP

function assets($file)
{
    $version = filemtime(DOCROOT.preg_replace('/^\//', '', $file));
    $retval = preg_replace('/(\.css|\.js)$/', '-version-'.$version.'$1', $file);
    return $retval;
}

<link rel="stylesheet" href="<?=assets('/assets/css/style.css')?>" />

これで以下の様にフィンガープリントが出来上がり!

<link rel="stylesheet" href="/assets/css/style-version-1472640446.css" />

ツッコミ等は@uratchまで~