Symfony 4をDeployerでデプロイしてSlackに通知する

Symfony Advent Calendar 2018 9日目の記事です。

概要

PHP製デプロイツールのDeployerを使ってSymfonyをデプロイする方法について書きます。おまけでSlackにデプロイ結果を通知する方法についても書きます。

環境など

Amazon Linuxで作業しました。Deployerのバージョンは 6.3.0 です。gitにあるSymfonyプロジェクトをデプロイする想定なのでGitHubに次のような準備を行いました。

$ composer create-project symfony/website-skeleton symfony4-deployer
$ cd symfony4-deployer
$ git add .
$ git commit -m "first commit"
$ git remote add origin git@github.com:cloned/symfony4-deployer.git
$ git push -u origin master

Deployerのインストール

Deployerは dep というコマンドを使って操作します。インストール方法は Deployer — Installation を参照してください。pharをダウンロードして配置する方法でもcomposerでインストールする方法でも dep というコマンドが利用できればOKです。

設定ファイル deploy.php を配置

dep コマンドが使えるようになったら、今度はデプロイするための設定ファイル deploy.php が必要です。このファイルは次のコマンドで雛形を作成することができます。

$ dep init

LaravelやSymfonyなど色々な選択肢が用意されており便利そうなのですが、この選択肢の SymfonySymfony 2 を想定しているのと、この手の設定はまず動く最小限を用意してから必要に応じて増やす方が理解しやすいので、ここでは最小設定の deploy.php を用意しました。

<?php
namespace Deployer;

require 'recipe/symfony4.php';

set('application', 'symfony4-deployer');
set('repository', 'git@github.com:cloned/symfony4-deployer.git');
set('env', [
    'APP_ENV' => 'prod',
]);

host('localhost')
    ->set('deploy_path', '~/deploy-path/{{application}}');

要点としては次のようになります。

  • 既に定義済みのレシピ symfony4.phprequire する
  • application(アプリ名)とrepository(gitリポジトリ)を設定する
  • Symfonyのenvがprodになるように APP_ENV を設定する
  • デプロイ対象のホストとパスを設定する

それぞれ少し解説します。

レシピに symfony4.php を利用する

Deployerにはレシピ(recipe)というものが用意されています。と書くとそのような仕組みがあるかのようですが実際のところ「良くあるタスクをあらかじめ定義しておいたPHP」というだけで、利用するにあたっては require するだけです。

ここで利用している recipe/symfony4.php はDeployer公式のものなのでcomposerなどで追加する必要はなくそのまま参照して利用できます。内容は直接コードを見た方がわかりやすいです。

deployer/symfony4.php at master · deployphp/deployer

設定を変更していく際に symfony4.php の定義をみて既にある定義を使うのか、上書きするのか、追加するのか、など考えますので元のレシピ(設定)を把握しておくことは重要です。といっても symfony4.php に関していえば数十行しかなく簡単に把握できると思います。

envをprodにする

<?php
set('env', [
    'APP_ENV' => 'prod',
]);

このように設定するとDeployerはコマンドを実行する際に先頭に export APP_ENV='prod'; と付け加えます。Symfonyのenvをprodにするためこのような設定を入れてあります。

この設定をせずにデプロイすると次のようなエラーになってしまいます。

PHP Fatal error: Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "WebProfilerBundle" from namespace "Symfony\Bundle\WebProfilerBundle".

これは composer install--no-dev で実行している(つまりrequire-devのものはインストールされない)にもかかわらず、SymfonyのenvはdevのためWebProfilerBundleクラスを読み込めずエラーになっています。

Symfonyのenvをprodにするには APP_ENV=prod と記述した .env ファイルを配置する方法もありますが、ここでは実行時の環境変数で設定を行いました。 APP_ENVについてはSymfonyの公式ドキュメントに記載がありますのでそちらも参照してください。

How to Deploy a Symfony Application C) Install/Update your Vendors

デプロイを実行する

これで準備が整ったのでデプロイを実行します。

$ dep deploy

うまくいけば次のように実行されたタスクが表示されます。

f:id:cloned:20181201212303p:plain:w290

デプロイ先は次のように設定していますので localhostSSH接続して deploy_path のパスに対してデプロイが行われます。

<?php
host('localhost')
    ->set('deploy_path', '~/deploy-path/{{application}}');

この例でのデプロイ後のアプリケーションパスは ~/deploy-path/symfony4-deployer/current になります。currentシンボリックリンクで実体は~/deploy-path/symfony4-deployer/releases/以下に存在します。releases/に配備したコードへのシンボリックリンクを張り替えるという方法になっています。この辺りはDeployerのコピー元であるRuby製デプロイツールのCapistranoと同じです。

デプロイを戻す

$ dep rollback

とすると直前のリリースにシンボリックリンクを張り替えます。これによりデプロイ前のコード(前回デプロイしたコード)にロールバックすることができます。ls -l current 等でシンボリックリンク先が変わっていることを確認すると理解しやすいと思います。

デプロイ設定を変更する

これで基本的なデプロイは完了です。ただ用途によって設定を変更したいことがあるかもしれません。例えば var/logvar/sessions はもともとデプロイごとに別ファイルになってしまわないようにcurrentと同じ場所にあるsharedディレクトリへのシンボリックリンクになるようになっていますが、var/files も同様にしたいとしましょう(var/filesは単にここでの例でSymfonyにはもともとありません)。

その場合は deploy.php に次の記述を追加します。

<?php
set('shared_dirs', ['var/log', 'var/sessions', 'var/files']);

元のレシピの symfony4.php に既に shared_dirs が定義されていますが var/files を追加して上書きしています。このように元のレシピを確認しながら必要に応じて設定を変更することができます。

他にも例えば symfony4.php には database:migrate タスクが定義されているので、デプロイ完了前にマイグレーションを実行するような設定を行うこともできます。

Slackに通知する

おまけですがデプロイが完了したらSlackに通知する設定も追加します。Slackに通知する実装はDeployer本体には含まれていませんが、別のリポジトリで色々なレシピが公開されておりそこにSlackのレシピが存在します。公式サイトにドキュメントも存在します。

Deployer — Slack recipe

まずはcomposerで各種レシピを追加します。

$ composer require deployer/recipes --dev

次に deploy.php にSlackに関する設定を追加します。成功時に通知したいだけであれば次の3行を追加するだけです。

<?php
require 'vendor/deployer/recipes/recipe/slack.php';
set('slack_webhook', 'https://hooks.slack.com/xxxxxxxx');
after('success', 'slack:notify:success');

slack_webhook のURLはSlack側で作成しておく必要があります。うまくいくと次のような通知が来るようになります。

f:id:cloned:20181201222525p:plain:w325

まとめ

Deployerを使ってSymfony 4をデプロイする方法を解説しました。PHPフレームワークのデプロイ設定があらかじめ用意されているのですぐに使い始められます。Symfony 4に限らず公式レシピをうまく使ってデプロイする際の参考になればと思います。