Deployer を使ってLaravel5 をDeploy してみる
Deployer はPHP 製のデプロイツールです。サクッと設定が書けて楽にデプロイ環境が構築できる印象でした。capistrano に似てるなって思いました。
今回はLaravel5.3 をデプロイする前提で書いていきます。
参考にしたのは
です。
環境
Laravel 5.3
Deployer 6.0.3
インストール
deployer.phar のダウンロード
$ curl -LO https://deployer.org/deployer.phar
パス通して dep
コマンドで使えるようにする
$ sudo mv deployer.phar /usr/local/bin/dep
実行権限付与
$ sudo chmod +x /usr/local/bin/dep
composer で project に Deployerのソースコードをinstall
$ composer require deployer/deployer
使い方
deploy.php の作成
$ dep init
Welcome to the Deployer config generator This utility will walk you through creating a deploy.php file. It only covers the most common items, and tries to guess sensible defaults. Press ^C at any time to quit. Please select your project type [Common]: [0 ] Common [1 ] Laravel [2 ] Symfony [3 ] Yii [4 ] Yii2 Basic App [5 ] Yii2 Advanced App [6 ] Zend Framework [7 ] CakePHP [8 ] CodeIgniter [9 ] Drupal [10] TYPO3
と聞かれるので
> 1
と入力。次に
Repository []:
と聞かれるのでgitのリポジトリを入力。ちなみにあとから設定できますので空でEnterでも全然構いません。
Contribute to the Deployer Development In order to help development and improve Deployer features in, Deployer has a setting for collection of usage data. This function collects anonymous usage data and sends it to Deployer. The data is used in Deployer development to get reliable statistics on which features are used (or not used). The information is not traceable to any individual or organization. Participation is voluntary, and you can change your mind at any time. Anonymous usage data contains Deployer version, php version, os type, name of the command being executed and whether it was successful or not, exception class name, count of hosts and anonymized project hash. If you would like to allow us to gather this information and help us develop a better tool, please add the code below. set('allow_anonymous_stats', true); This function will not affect the performance of Deployer as the data is insignificant and transmitted in separate process. Do you confirm? (yes/no) [yes]:
> yes
とすると
Successfully created: /path/to/proj/deploy.php
となります。
deploy.php ですが、私は以下のようにしました。
<?php namespace Deployer; require 'recipe/laravel.php'; // Project name set('application', 'my_project'); // Project repository set('repository', 'git@github.com:hoge/hoge.git'); // [Optional] Allocate tty for git clone. Default value is false. set('git_tty', true); // Shared files/dirs between deploys add('shared_files', ['.env']); set('shared_dirs', [ 'storage/app', 'storage/framework/cache', 'storage/framework/sessions', 'storage/framework/views', 'storage/logs' ]); // Writable dirs by web server add('writable_dirs', []); set('bin/php', function () { return '/home/ubuntu/.phpenv/shims/php'; }); // Hosts host('hogehoge.com') // ← ホスト名 もしくは Global IP ->stage('production') ->user('ubuntu') ->port(22) ->identityFile('~/.ssh/id_rsa') ->set('deploy_path', '/path/to/project/'); // Tasks task('build', function () { run('cd {{release_path}} && build'); }); after('deploy', 'deploy:db_seed'); desc('Execute artisan db:seed'); task('deploy:db_seed', function () { $output = run('{{bin/php}} {{release_path}}/artisan db:seed --class=UsersTableSeeder'); writeln('<info>' . $output . '</info>'); $output = run('{{bin/php}} {{release_path}}/artisan db:seed --class=SomethingTableSeeder'); writeln('<info>' . $output . '</info>'); }); // [Optional] if deploy fails automatically unlock. after('deploy:failed', 'deploy:unlock'); // Migrate database before symlink new release. before('deploy:symlink', 'artisan:migrate');
解説していきます。
set('repository', 'git@github.com:hoge/hoge.git');
git のリポジトリのurlです。
set('git_tty', true);
これを true にすると http で git 接続してる場合、Deployコマンド実行後、username と password の入力プロンプトが表示されます。ssh で git に接続する場合はfalse でOKです。
set('shared_dirs', []);
ここに入力されたディレクトリは current
ディレクトリの中に実体が作られず、shared
ディレクトリへのシンボリックリンクが貼られます。この辺はcapistrano と同じですね。
deployer の仕組みとして、deploy すると毎回、その時の最新のバージョンのソースコードが current
ディレクトリに入ります。(これもシンボリックリンクなのですが)
(因みにそこがルートになるので、current の下は app とか .env とかが置かれています。)
つまりデプロイするたびに current
ディレクトリが全て上書きされるってことです。
でもそうするとLogやらキャッシュやらはどうなるの??毎回消えちゃうの??って話になりますよね。それを回避するのがこの shared
っていう仕組みです。消したくないやつをここに記述します。
因みに set
としているのは、 add
をつかうと例外で死ぬためです。
add を使うと、
[Deployer\Exception\Exception] Can not share same dirs `storage/app` and `storage`.
上記のエラーがでました。色々調べてコアファイルもみたんですが、このshared_dirs
は下記ファイルで同じディレクトリ or 親ディレクトリが存在していないかのチェックをしているのですが、
vendor/deployer/deployer/recipe/deploy/shared.php
その判定ロジックが
<?php //〜 foreach (get('shared_dirs') as $a) { foreach (get('shared_dirs') as $b) { if ($a !== $b && strpos(rtrim($a, '/') . '/', rtrim($b, '/') . '/') === 0) { throw new Exception("Can not share same dirs `$a` and `$b`."); } } }
となっていました。それで何故か
get('shared_dirs')
の返り値が、自ら設定した
[ 'storage/app', 'storage/framework/cache', 'storage/framework/sessions', 'storage/framework/views', 'storage/logs' ]
ではなく、
[ 'storage', 'storage/app', 'storage/framework/cache', 'storage/framework/sessions', 'storage/framework/views', 'storage/logs' ]
となっていました。 これでは ループが 1つめのforeach の 2つめの値の
'storage/app',
になったとき、
if('storage/app/' !== 'storage/' && strpos('storage/app/', 'storage/') === 0){ // 試合終了 }
となって試合終了します。
まぁ色々謎なんですが、set つかうと
[ 'storage/app', 'storage/framework/cache', 'storage/framework/sessions', 'storage/framework/views', 'storage/logs' ]
になるので大丈夫です。
追記
なんか、公式でも
set('shared_dirs', []);
と set
が使われていました。
なんか僕が勝手に add
使ってハマってたみたいでした。
add('shared_files', ['.env']);
shared_dirs
のファイル版です。Laravel5 の場合はこの .env だけでOKでしょう。
add('writable_dirs', []);
List of dirs which must be writable for web server.
とありますので、webサーバーが書き込めるようにPermission をよろしく設定してくれるのでしょう。
set('bin/php', 〜
set('bin/php', function () { return '/home/ubuntu/.phpenv/shims/php'; });
僕はphp は phpenv 使っているので(本番環境でもその予定)、そのための設定です。これやらないと /usr/bin/php
使おうとして死にました。
host('hogehoge.com')
host('hogehoge.com') // ← ホスト名 もしくは Global IP ->stage('production') ->user('ubuntu') ->port(22) ->identityFile('~/.ssh/id_rsa') ->set('deploy_path', '/path/to/project/');
stage は production とか staging とか設定します。多分なんでもよい。
デプロイするときに
$ dep deploy production
上記のように環境を記述してコマンド実行するので、その時に名前が一致しているstage の host 設定を使うということです。
task('artisan:db:seed',
desc('Execute artisan db:seed'); task('artisan:db:seed', function () { $output = run('{{bin/php}} {{release_path}}/artisan db:seed --class=UsersTableSeeder'); writeln('<info>' . $output . '</info>'); $output = run('{{bin/php}} {{release_path}}/artisan db:seed --class=SomethingTableSeeder'); writeln('<info>' . $output . '</info>'); });
自分の好きなタスクを設定できます。 試しにdb:seed コマンドを実行するタスクを書いてみました。
あとは
$ dep deploy production -vvv
(-vvv は詳細表示。)
を実行してログをぼけーっと眺めるだけでよろしくやってくれます。
以上です。