読者です 読者をやめる 読者になる 読者になる

コネヒト開発者ブログ

コネヒト開発者ブログ

小規模PHPアプリケーションをDeployerでサッとデプロイする話

f:id:fortkle:20160728164803g:plain

こんにちは! 東京なのに周辺にポケストップが1つもない田舎に住んでいます、@fortkle です(世田谷公園の徒歩圏内に引っ越したいです)。

さて、みなさんはPHPアプリケーションのデプロイツールに何を使っているでしょうか。
今回コネヒトで Deployer というPHPで書かれたデプロイツールを採用したのですが、なぜDeployerなのかという理由と、実際に使っているおすすめの設定をいくつか共有したいと思います。
※ Deployerのインストール方法や基本的な使い方を知りたい場合は既にインターネット上に良い記事がたくさんあるのでそちらを参考にしてみてください。

デプロイツール、どうする?

今回、新しく小規模PHPアプリケーションをデプロイする機会があったため下記の条件で新しくデプロイツールの選定を行いました。

  • PHPのアプリケーションなので デプロイツールもPHP製のもの を採用したい
  • 対象ホストが1台〜程度の小規模アプリケーションなので サッと手軽にデプロイ したい
  • CSSやJavaScriptなどのビルドツールの生成物 をGit管理したり、対象ホスト上でコンパイルしたりせずにデプロイしたい

この条件を元にいくつかのデプロイツールを試し、最終的に Deployer を採用しました。

Deployerによるデプロイの利点

1. PHPに統一された世界

これまでコネヒトではデプロイツールとしてRuby製のCapistranoを利用してきました。Capistranoはデプロイツールのデファクトスタンダードとなっている優れたツールですが、Rubyで書かれているためPHPでサービス開発をしているコネヒトでは下記のような課題がありました。

  • PHPのプロジェクトなのにデプロイするためだけにRubyやgemのバージョンに気を使わないといけない
  • 拡張・運用するにもRubyで記述しなければならないため、デプロイ周りの処理の運用・改善をする人が限られる

PHPで書かれたDeployerなら、この問題はありません。

2. サッと手軽にデプロイできる

小規模なアプリケーションなのであまりコストを掛けずに、できればWebエンジニアだけでサッと手軽にデプロイできるぐらいが理想です。そのためにはデプロイツール自体がシンプルで簡単であることが求められます。

この点において、Deployer は他のデプロイツールに比べて完成度は高く、学習コストは低いという使いやすいツールになっています。今回は小規模のアプリケーションですが、大規模なアプリケーションのデプロイにも十分耐えうる完成度だと思います。

試しに 公式のドキュメント に記載されているDeployerの設定ファイルを見てみましょう。 ちなみにDeployerの設定ファイルはこの PHP 1ファイルだけ です。

<?php

// Symfonyのレシピをrequire
require 'recipe/symfony.php';

// デプロイ先となるホストサーバーの設定
server('prod', 'host', 22)
    ->user('name')
    ->forwardAgent() // エージェントフォワーディングを有効化
    ->stage('production')
    ->env('deploy_path', '/your/project/path'); // デプロイするパスを指定

// デプロイするコードを管理しているリポジトリ
set('repository', 'git@github.com:org/app.git');

どうでしょうか?Deployerに触った事がない人でもコードを見るだけで何を設定しているのか想像できそうですね!

Deployer は設定ファイルだけでなく、インストールもcomposerのようにpharファイルを置くだけで使うことができますし、デプロイの実行も簡単です。詳細については 公式のドキュメントを読んでみてください。

3. 生成物のデプロイ

小規模PHPアプリケーションをデプロイする際に「CSSやJavaScriptなどのビルドツールの生成物をどうデプロイするか」という論点があります。

方法としては生成物自体をGitリポジトリに含めたり各ホストでコンパイルしたりする方法が思い浮かびますが、Gitリポジトリに含めることはリポジトリが肥大化する原因になりますし、各ホストでコンパイルを行うのもホスト数が1台増えるたびにコンパイル環境を構築する必要があります。何より全台で同じことをするのはリソースの無駄です。

この点において Deployer はアップロード機構が標準で用意されているため、ローカルでコンパイルしたCSSやJavaScriptなどのビルドツールの生成物を簡単に各ホストに配布することができます。

実際に使っているおすすめの設定

コネヒトで実際に使用している設定をいくつか共有したいと思います。

ローカルアップロードと確認

アップロード用のTaskを設定すればローカルにあるファイルを各ホストにアップロードすることができます。

<?php

task('deploy:upload', function () {
    if (askConfirmation('ローカルのCSS, JSをデプロイ先にアップロードしてもよろしいですか?', true)) {
        $appFiles = [
            'webroot/css',
            'webroot/js',
        ]; 
        $releasePath = env('release_path');

        foreach ($appFiles as $file) {
            upload("../{$file}", "{$releasePath}/{$file}");
        }
    } else {
        writeln("<info>デプロイを中止しました。</info>");
        die();
    }
})->desc('Upload static file');

upload("../{$file}", "{$releasePath}/{$file}"); の部分が実際にアップロードしている箇所で、$appFiles で宣言したファイルとディレクトリをアップロードします。

ポイントは2点あります。
1点目は askConfirmation()を使って本当にローカルのファイルをアップロードするか確認している点です。意図せず誤ってローカルのファイルをアップロードしてしまったり、中途半端な状態のファイルをアップロードしたりすることをある程度防ぐことができます(CIなどからではなく手動で実行する場合100%防ぐことはできません)。

$ php deployer.phar deploy --tag v0.1.0 production                                                                                                                                          
   
✔ Executing task deploy:prepare
✔ Executing task deploy:release
✔ Executing task deploy:update_code
➤ Executing task deploy:upload
ローカルのCSS, JSをデプロイ先にアップロードしてもよろしいですか? [Y/n] 

2点目は askConfirmation()の第2引数を true にすることでデフォルトでアップロードするようにしていることです(通常はデフォルトfalse)。これの何が嬉しいかというと、Deployerにはyes/noのような対話式の処理を無視してデフォルト値を使ってくれる --no-interaction というオプションがあるので、CIサーバーなど自動でデプロイコマンドを叩く際にそのオプションを付ければ対話処理をスキップしてデプロイが実行できます。

// 通常
$ php deployer.phar deploy --tag v0.0.2 production

// 対話無視(デフォルト値を使う)→ CIなどで。
$ php deployer.phar deploy --tag v0.0.2 --no-interaction production

ロールバックのヒントを表示

デプロイだけでなくロールバックが簡単に実行できることも重要です。 Deployer は$ php deployer.phar rollback production などと打てば簡単にロールバックできる機構が最初から設定されています。
しかし、ロールバックが必要な時というのは緊急度の高いバグなどが発生している状況が多くそういう時に限って人はミスをしがちです。そこで万が一の際に慌てずにミスなく簡単にロールバックできるようにヒントを表示*1してみましょう。

<?php

task('rollback_hint', function () {
    $stage    = input()->getArgument('stage');
    $message  = "\nヒント:ロールバックしたい場合は以下のコマンドを実行しましょう\n";
    $message .= "<info>$ php deployer.phar rollback {$stage}</info>\n\n";
    $message .= "ヒント:タグを指定してデプロイしたい場合は以下のコマンドを実行しましょう\n";
    $message .= "<info>$ php deployer.phar deploy --tag {TAG_NAME} {$stage}</info>\n";
    writeln($message);
})->desc('Show rollback hint message');

上記コードを 設定ファイルdeploy.phpに記述してデプロイに成功した後に表示してあげると下記のようにヒントが表示されます。

$ php deployer.phar deploy --tag v0.1.0 production                                                                                                                                             
✔ Executing task deploy:prepare
✔ Executing task deploy:release
✔ Executing task deploy:update_code
✔ Executing task deploy:symlink
✔ Executing task cleanup
➤ Executing task success
Successfully deployed!
✔ Ok
➤ Executing task rollback_hint

ヒント:ロールバックしたい場合は以下のコマンドを実行しましょう
$ php deployer.phar rollback production

ヒント:タグを指定してデプロイしたい場合は以下のコマンドを実行しましょう
$ php deployer.phar deploy --tag {TAG_NAME} production

このように実行すべきコマンドがそのまま表示されるのでコピペするだけで安心してロールバックすることができます。

SSHエージェントフォワーディング

deployerはSSHエージェントフォワーディングをサポートしています。 デプロイ先サーバー上であっても、ローカルにある秘密鍵を使ってGithubとの認証ができるので非常に便利です。 (事前にローカルで $ ssh-addをして秘密鍵を登録しておく必要があります )

<?php

server('prod', 'host', 22)
    ->user('name')
    ->forwardAgent() // ←この1行を追加して有効化
    ->stage('production')
    ->env('deploy_path', '/your/project/path');

最後に

いかがだったでしょうか? 今回は Deployer を選んだ理由とおすすめの設定をいくつかご紹介しました。
Deployer は本当に簡単にデプロイを自動化できるので、いままでデプロイツールを使ったことがない人からこれまで他のツールを使っていた方まで全員にオススメできます。
アプリケーションの規模や構成によって適したデプロイツールは変化していきますが、小規模アプリケーションのデプロイで Deployer を試してみてください!

*1:このアイデアは 失敗する前提でデプロイする という記事を参考にしました。おもてなし大事!