Home > アーカイブ > 2014-09

2014-09

Vagrant のプロビジョン時間を削減する vagrant-cachier プラグインが良い

この記事の所要時間: 529

Vagrant でプロビジョンを行う際に時間がかかるのが、yum などを使ったパッケージのインストールです。ネットワーク環境が悪い場合、ダウンロード自体に時間がかかるため、大きな待ち時間が発生します。

vagrant

vagrant-cachier プラグインを使うことで、このダウンロード時間を削減することができます。

vagrant-cachier プラグイン

vagrant-cachier プラグインは、プロビジョンなどでダウンロードしたパッケージをキャッシュしておくことで、次回以降のダウンロード時間を削減しようというプラグインです。

https://github.com/fgrehm/vagrant-cachier

vagrant-cachier プラグインの効果

これは効果を見たほうが早いと思うで、vagrant-cachier プラグインを導入した場合の効果についてです。

vagrant destroy で VM を破棄した後に、vagrant up を実行して、その実行時間を time コマンドで計測しています。

$ vagrant destroy -f
$ time vagrant up

今回、計測に利用した Vagrantfile は、ある PHP プロジェクトで利用しているものです。Ansible によるプロビジョン(VM内で実行)を行っており、Composer の実行や PHPUnit による自動テストも行っています。これらは本プラグインとは無関係なのですが、実際に使う場面で効果があるか見たかったので、この環境で計測しています。

  • プラグインなし

比較のために vagrant-cachier プラグインを入れていない状態で、vagrant up を実行した結果です。

vagrant up  4.64s user 2.19s system 0% cpu 11:36.15 total
  • プラグインインストール済み(初回)

vagrant-cachier インストールして、初回(キャッシュが無い状態)の実行時間です。

vagrant up  6.18s user 2.69s system 1% cpu 12:33.26 total
  • プラグインインストール済み(2回目)

vagrant-cachier インストール後、キャッシュがある状態での実行時間です。

vagrant up  6.26s user 2.68s system 2% cpu 6:42.31 total
  • 結果

結果を表にまとめたのが以下です。実行時間を比較してみると、プラグインをインストールして、キャッシュがある状態なら、実行時間が約半分になりました。これは大きな効果ですね。

実行時間
プラグイン無し 11.36.15
プラグイン有り(キャッシュ無し) 12.33.26
プラグイン有り(キャッシュ有り) 6.42.31

インストール

vagrant-cachier プラグインをインストールするには、vagrant plugin install コマンドを実行するだけです。

$ vagrant plugin install vagrant-cachier

Vagrantfile への記述

vagrant-cachier プラグインを有効にするには、Vagrantfile に下記の設定を行います。config.cache.scope では、キャッシュスコープを設定します。

下記では、:boxを指定しており、これは、プロビジョンでインストールしたパッケージを Box 単位でキャシュします。同一 Box を使う Vagrantfile であれば、別の VM でもキャッシュを共有することができます。

私の用途であれば、この設定が使いやすそうです。

あとは、通常どおり、vagrant up を行うとプラグインが有効となり、キャッシュを行うようになります。

Vagrant.configure("2") do |config|
  # (snip)

  if Vagrant.has_plugin?("vagrant-cachier")
    config.cache.scope = :box  
  end

  # (snip)
end

その他のキャッシュスコープやオプションついては、vagrant-cachier のサイトを参照にして下さい。

http://fgrehm.viewdocs.io/vagrant-cachier/usage

何をキャッシュしているのか

プロビジョンで追加したパッケージをどうやってキャッシュしているのか気になったので、仕組みを見てみました。

コードを見たところ、CentOS の場合は、ゲストの /var/cache/yum/tmp/vagrant-cache/yum へのシンボリックリンクになっています。そして、この /tmp/vagrant-cache/ は、ホスト側との synced_folder となっており、~/.vagrant.d/cache/BOX_NAME/ がマウントされています。

つまり、ゲストで yum install コマンドでインストールすると、/var/cache/yum にパッケージのキャッシュファイルが保存されます。これは、ホストの ~/.vagrant.d/cache/BOX_NAME/yum と synced_folder で同期しているので、結果としてホストにこのキャッシュファイルが保存されます。

これは、なかなか面白い仕組みですね。

さいごに

vagrant-cachier プラグインを使うことで、プロビジョンの実行速度が大きく改善されます。プロビジョンコードを書くと、検証のために何度もプロビジョンを実行することになり、その度に待たされていました。このプラグインを使うことで、その時間が削減できるので、プロビジョンが捗ります。

ちなみに、このプラグインは、CakePHPで学ぶ継続的インテグレーション を読んで、知りました。

いま読み進めているところですが、PHP で CI したい人には嬉しい内容になっています。書評は、また別エントリで書きますね。

  • コメント (Close): 0
  • トラックバック (Close): 0

Ansible で、複数サーバの RPM を一括で更新する

この記事の所要時間: 942

Bash 脆弱性が出ましたね。対策がまだの方はお早めに。

th_ansible_logo_black_square

修正 RPM が提供されているとはいえ、複数サーバにログインして、yum update していくのは、骨が折れる作業です。元から構成管理ツールを導入していて、一括更新出来る場合は良いのですが、なかなか導入できていないところも多いでしょう。

このエントリでは、Ansible を使って、複数サーバに対して、一括で RPM 更新を行う方法を見ていきます。

Ansible インストール

Ansible の操作を行う PC or サーバにインストールします。これは ansible コマンドを実行する環境にのみインストールします。例えば、サーバ管理者の PC などです。チームで行う場合は、操作用のサーバにインストールして、SSH で操作サーバにログインして、実行すると良いでしょう。

OSX なら、Homebrew で入れるのが簡単です。

$ brew install ansible

RHEL / CentOS なら、EPEL で配布されているので、yum でインストールできます。

$ rpm -ivh http://ftp.riken.jp/Linux/fedora/epel/6/i386/epel-release-6-8.noarch.rpm
$ yum -y install ansible

インストールが完了したら、ansible コマンドが動作するか確認しておきます。

$ ansible --version                                                                                                                                                                                                                                                                                            ansible 1.7.1

対象ホスト

対象ホストは、SSH でログインができれば、別途インストールは不要です。(実際は、Python がインストールされている必要があるのですが、多くの Linux 環境ではインストールされています。)

あと、リモートホスト上で実行したい操作に root 権限が必要な場合(RPM の更新には必要)は、root ユーザでログインするか、SSH ログインするユーザが sudo できる状態にしておく必要があります。

対象ホストをインベントリファイルに記述

処理対象のホストを指定するためにインベントリファイルを作成します。インベントリファイルには、対象サーバのホスト名や接続情報を記述します。

下記では、host1.exmaple.com と host2.example.com を処理対象のホストとして指定しています。

$ vim hosts
host1.example.com
host2.example.com

インベントリファイルでは、SSH接続情報をパラメータとして指定することができます。良く使うパラメータは以下です。

  • ansible_ssh_port = SSH接続ポート(22 以外を使う場合に指定)
  • ansible_ssh_user = SSH接続ユーザ名(指定が無ければ、ansible コマンドを実行したユーザ)
  • ansible_ssh_pass = SSH接続パスワード(パスワード認証の場合。パスワードを書くのは好ましくないので、–ask-pass をオプションを指定した方が良い)
  • ansible_ssh_private_key_file = 公開鍵認証時の秘密鍵ファイルパス

インベントリファイルでは、下記のように指定します。

host1.example.com ansible_ssh_user=user1 ansible_ssh_private_key_file=/path/to/secret_key
host2.example.com ansible_ssh_user=ec2-user

ホストをグループ化(ロールやプロジェクト等)したい場合、インベントリファイルを分ける(projectA_hosts, projectB_hosts)か、グループを指定することができます。

イベントリファイルでグループを指定する場合は、下記のように記述します。

[groupA]
host1
host2

[groupB]
host3

ansible コマンドの実行

ansible コマンドを実行してみましょう。

ansible コマンドを使って、リモートホストでコマンドを実行する場合、下記のようにオプションを指定します。

$ ansible 処理対象ホスト -i イベントリファイル -m shell -a "コマンド"

ansible コマンドに続いて、処理対象のホストを指定します。これはイベントリファイルに含まれている必要があります。全てのホストを対象とする場合は、allを指定します。グループ内のホストを対象をする場合は、グループ名を指定します。

-i オプションでイベントリファイルを指定します。

そして、実行するモジュールを指定します。ここでは、shell モジュールを使って、コマンドをリモートホストで実行したいので、-m shell -a オプションを指定します。

下記が実行例です。ここでは、hosts に書かれた全てのホスト上で、uname -a コマンドを実行します。それぞれのホストでの実行結果が表示されており、コマンドが実行できたことが確認できます。

$ ansible all -i hosts -m shell -a "uname -a"
host1.example.com | success | rc=0 >>
Linux host1.example.com 2.6.32-431.11.2.el6.x86_64 #1 SMP Tue Mar 25 19:59:55 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

host2.example.com | success | rc=0 >>
Linux host2.example.com 2.6.32-431.11.2.el6.x86_64 #1 SMP Tue Mar 25 19:59:55 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

ansible コマンドには、shell モジュール以外にも多くの機能があるのですが、ここではこのモジュールのみ利用します。

RPM のバージョン確認

では、実際に RPM の更新を ansible コマンドで実行してみましょう。ここでは、対象 RPM を bash とします。

まずは現在の RPM のバージョンを確認しておきます。もちろん、これにも ansible コマンドを使います。RPM のバージョン確認には、rpm -qv コマンドを使います。

実行結果が以下です。それぞれの bash のバージョンが表示されています。host1 は、現段階(2014/09/25)での最新版となっていますが、host2は、まだ古いままとなっています。

$ ansible all -i hosts -m shell -a "rpm -qv bash"
host1.example.com | success | rc=0 >>
bash-4.1.2-15.el6_5.1.x86_64

host2.example.com | success | rc=0 >>
bash-4.1.2-15.el6_4.x86_64

ansible で RPM を更新

RPM の更新を行ないます。

RPM の更新では、yum -y update bash コマンドで行ないます。通常、yum updateすると Yes or No の確認が入るのですが、ここでは自動実行するので、-y オプションを付けておきます。

では実行してみましょう。

$ ansible host1.example.com -i hosts -m shell -a "yum -y update bash" 
host1.example.com | success | rc=1 >>
Loaded plugins: downloadonly, fastestmirror, securityYou need to be root to perform this command.

おっと、エラーが発生しました。yum update では、root 権限が必要なためです。では、--sudoオプションを付けて、再実行してみましょう。

次は、無事に更新することができました。

$ ansible host1.example.com -i hosts --sudo -m shell -a "yum -y update bash" 
host1.example.com | success | rc=0 >>
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile

(snip)

Updated:
  bash.x86_64 0:4.1.2-15.el6_5.1

Complete!

念のため、バージョンを確認しておきます。両ホスト共に最新版となりました。

$ ansible all -i hosts -m shell -a "rpm -qv bash"
host1.example.com | success | rc=0 >>
bash-4.1.2-15.el6_5.1.x86_64

host2.example.com | success | rc=0 >>
bash-4.1.2-15.el6_5.1.x86_64

さいごに

Ansible で、複数ホストの RPM を更新してみました。

本文で見てきたように、Ansible は、SSH ログインができるリモートホストなら、エージェントなどをインストールしなくても利用できるのが利点の一つです。ツールによる構成管理ができていない環境でも、操作用の環境にさえ Ansible をインストールすれば気軽に使いはじめることができます。

OpenSSL に続き、今回の Bash 脆弱性発覚、もちろん RPM 更新以外にもサーバ運用では何かと一括で操作を行うタスクが発生します。

Ansible を活用して、こうしたタスクの手間を削減してみてはどうでしょう。

なお、Ansible には、今回紹介したスポットでのコマンド実行の他にも、構成管理やデプロイなど、サーバ構築や運用のタスクを自動化する機能があります。10/11 に開催される PHP カンファレンスでは、そのあたりをお話したいと思いますので、ぜひご参加下さい:D

http://phpcon.php.gr.jp/w/2014/

参考

Ansible Documentation
Ansible チュートリアル | Ansible Tutorial in Japanese

  • コメント (Close): 0
  • トラックバック (Close): 0

PhpStorm 8 で、Vagrant VM の PHPUnit を IDE から実行する

この記事の所要時間: 628

PhpStorm 8 が、リリースされましたね!

PHP 5.6 や Laraevel の blade 対応など気になる新機能があるのですが、その中でも、注目なのが、PHPUnit by Remote Interpreter です。

この機能を使うことで、Vagrant VM にインストールされている phpunit をホストの PhpStorm から直接実行することができます。Vagrant による開発が普及してきた今では必須の機能といえるでしょう。

利用するには、いくつか設定が必要となるので、その手順を書いてみます。

対象の PHP アプリケーション

このエントリでは、以下の環境で PHP アプリケーション開発しているという想定で進めていきます。

  • Vagrant VM で PHP アプリケーションを実行
  • PHPUnit は、Composer でインストール
  • PHPUnit の設定は、phpunit.xml に記述

PHP Interpreter の設定

はじめに PHP Interpreter に Vagrant VM の php を指定します。

Preferences – PHP を開いて、Interpreter プルダウンメニュー横にある ... をクリックします。

th_phpstorm-php

クリックすると Interpreters ダイアログが表示されます。まず、左上にある をクリックして、Remote...を選択します。

th_phpstorm-phpunit

Configure Remote PHP Interpreter ダイアログが表示されるので、Vagrant を選択します。選択すると、Vagrant 用の入力フォームに表示が変わり、各フォームに自動で値が入ります。ここでは編集せずに進みます。もし必要があれば変更して下さい。

th_phpstorm-configure-remote-php-interpreter

OKを押すと、Vagrant VM と通信して、設定項目が妥当か検証が行われます。問題無ければ、ダイアログが閉じます。

Interpreter ダイアログの左側ツリーには、追加したRemote PHP 5.5が表示されます。右側フォームの General には、Vagrant VM にインストールされている PHP と Xdebug のバージョンが表示されるので、念のため確認しておくと良いでしょう。

OKを押して、ダイアログを閉じます。

th_phpstorm-interpreter-2

PHP に戻ると、設定した Interpreter が選択されています。OKをクリックして、PHP Interpreter の設定は完了です。

th_phpstorm-php-2

PHPUnit By Remote Interpreter の設定

次に PHPUnit の設定を行ないます。Preferences – Project Settings – PHP – PHPUnit を開きます。

PHPUnit ダイアログの左上に があるので、これをクリックして、By Remote interpreterを選択します。

th_phpstorm-phpunit

PHPUnit By Remote Interpreter ダイアログが開きます。Interpreter に先ほど登録したRemote PHP 5.5を選択して、OK をクリックします。

th_phpstorm-phpunit-by-remote-interpreter

ダイアログが閉じると、右側に PHPUnit の設定項目が表示されます。

PHPUnit 関連のファイルは、Composer のオートローダーから読み込むので、PHPUnit library には、Use custom autoloader を選択します。Path to script が表示されるので、Composer の autoload.php のパスを設定します。なお、この設定は VM 内でのパスを指定する必要があるので注意して下さい。(テキストボックス横の ... をクリックすると、VM 内のパスを GUI で指定することができます。)

次に、Test Runner の Default configuration file にチェックを入れて、phpunit.xml のパスを指定します。(phpunit.xml を利用していない場合、これは不要です。)ここのパスも VM 上のパスになります。

設定が完了したら、Apply もしくは OK をクリックします。これで、PHPUnit By Remote Interpreter の設定は完了です。

th_phpstorm-phpunit-2

Run/Debug Condigurations での PHPUnit 設定

最後に、IDE からテストを実行するために、Run/Debug Configurations にて PHPUnit の設定を行ないます。

画面左上にある をクリックして、PHPUnitを選択します。(PHPUnit on Server ではないので、注意して下さい。)

Name には、それと分かる名称を記述します。ここでは PHPUnit on Vagrantとします。

次に、Test Runner の Test scope を選択します。ここでは、前項で phpunit.xml へのパスを指定しているので、Defined in the configuraion fileを指定します。(テストディレクトリを指定したい場合は、Directoryを選択して、対象のディレクトリを記述して下さい。)

OKをクリックして、設定は完了です。

th_phpstorm-run-debug-configurations

PHPUnit の実行

いま設定した PHPUnit を実行してみます。ウィンドウメニューバー右上にて、下記のように設定したPHPUnit on Vagrantを選択した状態で、右側の矢印をクリックするとテストが実行されます。( Run を実行すれば良いので、メニューから選択しても、CTRL + R でも良いです。)

th_phpstorm-menu

テストが実行できました!

th_phpstorm-phpunit-panel

IDE から Vagrant VM の PHPUnit を実行する良さ

実際に使ってみて良かった点です。

1. 操作が楽

これまでテストを実行する時は、ターミナルアプリケーション に遷移して、phpunit コマンドを実行していました。それが、PhpStorm 内で CTRL + R だけで実行できるようになりました。ちょっとした手間ですが、同じウィンドウで済ませられるので楽です。

2. diff が見やすい

アサーションでテストが失敗した時に、期待した値と実際の値と差分を表示することができます。この差分表示は、コードの変更差分と同じ形式で、左に期待した値、右に実際の値を表示してくれます。これは phpunit コマンドの実行結果に比べて、分かりやすいです。

th_phpstorm-comparison-failure

3. 各テストの実行時間が分かる

テスト全体の実行時間だけでなく、各テストケースの実行時間も記録されているので、一覧で確認することができます。もちろん、実行時間で並べ替えもできるので、遅いテストの確認なども簡単です。

th_phpstorm-time-elapsed

さいごに

PHPStorm 8 の PHPUnit By Remote Interpreter を使って、PhpStorm から Vagrant VM にある PHPUnit を実行してみました。

上でも書きましたが、設定して、開発サイクルでテストを実行すると、想像していた以上に楽です。テストの実行が気軽にできますし、結果も分かりやすいです。

Vagrant を使って、PHP アプリケーションを開発しているなら、ぜひ設定してみて下さい。

参考

http://confluence.jetbrains.com/display/PhpStorm/Running+PHPUnit+tests+over+SSH+on+a+remote+server+with+PhpStorm

  • コメント (Close): 0
  • トラックバック (Close): 0

PHP コードの整形はプログラマがやるべきことじゃない

この記事の所要時間: 98

PHP には、PSR が策定されたおかげで、これをベースにコーディングスタイルがある程度整ってきました。

ここ近年開発がはじまったプロジェクトなら、PSR-1/2 をコーディングスタイルとして採用しているプロジェクトも多いのではないでしょうか。

せっかく採用したなら、実際に書くコードはできるだけこの基準に沿うようにしたいものです。ただ、ここにあまり手間をかけるのも本末転倒です。そこで、手間をかけずに、コーディングスタイルに従えるような方法を模索してみました。

開発環境には、PhpStorm を使う前提です。

PhpStorm の PSR1/PSR2 ルール

まず、PhpStorm の Code Style で、PSR1/PSR2 をルールとして設定しました。

プロジェクト毎に規定したいので、Scheme はProjectにして、set from...をクリックして、Predefined Style から PSR1/PSR2を選択します。

code-format1

これで、PSR-1/2 のルールがコーディングスタイルへ設定されます。

コーディングスタイルによるコード整形(Reformat)

PHP コードを書いていけば、インデントやブレース位置など自動で適用してくれます。

また、フレームワークで自動生成されたコードなど既存のコードに対して、整形する機能があります。それが Reformat Codeという機能です。

Search Everywhere(⌘ ⌘)から、「reformat」と入力して、選択しても良いですし、⌘ + option + enter でも ok です。

Reformat Codeを実行すると、下記のようなダイアログが表示されます。適用範囲の選択やオプションが選択できます。Optimize importsにチェックを入れておくと不要な import文を削除してくれたりすので、チェックしておくと良いでしょう。Rearrenge entriesにチェックを入れると、メソッドの順序を並べ替えたりするので、これは外しておきます。

Runを実行するとコーディングスタイルに従って、コードが整形されます。

code-format2

例えば、下記のようなコードがあるとします。

class Foo{
    public function hello($show=false) { if($show){print "Hello".PHP_EOL;}
}    
}

これを Reformat Code すると、以下のように整形されます。

<?php

class Foo
{
    public function hello($show = false)
    {
        if ($show) {
            print "Hello" . PHP_EOL;
        }
    }
}

Reformat Code は、単一ファイルだけでなく、特定のディレクトリ以下の全てのファイルに対して行うこともできるので、一括で整形するのも簡単です。

PhpStorm PSR1/2 スタイルへの違和感

設定も簡単で良かったのですが、Reformat Code でコード整形すると、これだけは気になるというコードがあります。

それは、クロージャをメソッドの引数に渡すコードです。

例えば、下記のようなコードがあります。

Route::post('/', function() {
    return View::make('index');
});

これを Reformat Code すると、下記のようになります。

Route::post(
    '/',
    function () {
        return View::make('index');
    }
);

うううん、これは気持ち悪い。。。Reformat する前の方が読みやすいし、行数も少なくて済みます。

コード整形のルールは、Code Styleの設定次第なので、該当箇所を特定して変更していました。

環境毎にいちいち設定?

日頃 iMac と MBA を使って開発しているので、PhpStorm はそれぞれの PC にインストールしています。設定は共有していないので、こうしたカスタマイズを行うと、それぞれに適用する必要があります。

また、PhpStorm は、時折うっかり設定を忘れてしまうようで、たまに再設定を行ったりします。

そして、チームで開発する際は、メンバーがそれぞれ該当箇所を設定するする必要があります。(チームメンバーで設定を共有するような仕組みが PhpStorm にあれば、良いのですが、まあそれは未来に期待して。)

設定自体はそれほど大変ではないですが、全ての環境で行うには手間がかかります。

PHP Coding Standards Fixer

じゃあ、PHP Coding Standards Fixer で、自動変換すれば良いじゃないかと思い、.git/hooks/pre-commitに仕込んだりしたのですが、これもそれぞれの環境で仕込む必要があり、それもまた手間です。

ちなみに、以下のような設定を書いてました。これは自動変換ではなく、コーディングスタイルに合致しないコードがあれば、警告を出して commit を reject する仕様になってます。

#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments.  The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".

#
# php-cs-fixer
#
PROJECTROOT=`echo $(cd ${0%/*}/../../ && pwd -P)`/
FIXER=php-cs-fixer.phar

if [ ! -e ${PROJECTROOT}${FIXER} ]; then
  echo "PHP-CS-Fixer not available, downloading to ${PROJECTROOT}${FIXER}..."
  curl -s http://cs.sensiolabs.org/get/$FIXER > ${PROJECTROOT}${FIXER}
  echo "Done. First time to check the Coding Standards."
  echo ""
fi

DIRECTORIES="app bootstrap public package"

for d in ${DIRECTORIES}; do
  php ${PROJECTROOT}${FIXER} fix $PROJECTROOT/src/${d} --verbose --dry-run --fixers=indentation,linefeed,trailing_spaces,unused_use,short_tag,visibility,php_closing_tag,braces,extra_empty_lines,include,controls_spaces,elseif,eof_ending,function_declaration
  if [ $? -ne 0 ]; then
    exit 1
  fi 
done

もう、PSR1/PSR2 そのままで良いんじゃないか

しばらく悶々としながら開発していたのですが、もう人間の好みは捨てて、ツールに委ねる方が良いのでは、という考えに至りました。

PhpStorm デフォルトの PSR1/PSR2 を適用すれば、かなりの部分は読みやすいコードに整形してくれます。クロージャの部分も読みにくいというより、好みではない(なんとなく気持ち悪い)という程度なので、これは慣れれば、どうということはなさそうです。

結果として、PhpStorm の PSR1/PSR2 をカスタマイズせず、そのままコーディングスタイルとして利用するようになりました。

コーディングスタイルを自動で適用

せっかくのコーディングスタイルですが、毎回、手で Reformat Code を実行するのは手間です。そこで、commit 時に自動で適用するようにしています。

Commit を実行した際に表示されるダイアログの右にある Before Commit の Reformat codeOptimize importsにチェックを入れておけば、commit 前にこれらを自動実行して、整形済のコードを commit してくれます。

code-format3

さいごに

本文でも書いたように、現在は、PhpStorm 標準のPSR1/PSR2ルールを利用しており、commit 時に自動で整形されるようにしています。IDE やエディタが複数混在していたり、人数が多くなると、CI などで一括管理した方が良いかもしれませんが、設定の手間と効果を考えると、今のところ、この運用で十分です。

PhpStorm の Reformat Code はなかなか良くできており、多少の好みくらいならカスタマイズせずに、ツールに寄り掛かる方が良いと実感しました。将来フォーマットが変わるかもしれませんが、それはそれで自動整形すれば良いだけです。

これだけツールが良くなると、コーディングスタイルを人間が気にすること自体が無駄な気がしてきて、ツールが勝手に決められたルールに従って整形してくれれば、それで良いという考えになってきました。

ちなみに、件のクロージャのスタイルは時間が経つにしたがって、気にならなくなってきました。引数が多い場面などは、かえってこの方が読みやすいんじゃないかという気さえしてきたので、まあ慣れの問題ですね。

  • コメント (Close): 0
  • トラックバック (Close): 0

Laravel 4 環境ごとの設定

この記事の所要時間: 213

Laravel には、アプリケーションの設定を環境によって切り替える機構があります。これを使うことで、開発環境、ステージング環境、本番環境、テスト環境で設定を切り替えることができます。

laravel

ここでは、Laravel 4.2 を対象とします。

環境設定の指定

環境設定の指定は、bootstrap/start.php の以下の箇所で行ないます。デフォルトでは、ホスト名がhomesteadの場合はlocal、それ以外はproductionとなります。

$env = $app->detectEnvironment(array(
  'local' => array('homestead'),
));

このdetectEnvironmentメソッドでは、クロージャが引数の場合、その戻り値を環境設定として扱うことができます。

私は、環境変数での切替の方が扱いやすいので、LARAVEL_ENVという環境変数の値を取得して、それを環境設定としています。環境変数に指定が無ければ、localをデフォルトの設定としています。

$env = $app->detectEnvironment(function () {
    if (getenv('LARAVEL_ENV')) {
        return getenv('LARAVEL_ENV');
    }

    return 'local';
});

環境変数であれば、Web サーバの設定なり、シェルの設定なり、アプリケーションの外から渡すことが容易なので、柔軟に設定を切り替えることができます。

例えば、あるプロジェクトでは、本番へのデプロイ時に.htaccessを動的に生成して、その中でSetEnv LARAVEL_ENV productionを記述するタスクを自動実行するようにしています。また、Heroku 環境では、アプリケーションに環境変数が設定できるので、そこでLARAVEL_ENV=herokuを設定しています。

環境ごとの設定

環境ごとの設定は、設定ファイルのディレクトリを作成することで指定することができます。

まず、メインとなるのが、app/config/以下の設定です。ここに上記で指定した環境設定をディレクトリとして作成して、その下に設定ファイルを設置すると、それが読み込まれます。

app/config/
  + local/      <--- local 用設定
    + app.php
    ...
  + production/ <--- production 用設定
    + app.php
    ...
  + heroku/     <--- heroku 用設定
    + app.php
    ...

設定は、まず、デフォルト(app/config/直下)の各ファイルが読み込まれ、環境ごとのディレクトリにある設定ファイルの内容がそれに上書かれるという動作になります。よって、環境ごとのディレクトリには、デフォルトから変更の必要があるファイルのみ設置します。また、設置したファイルでも全ての要素を記述する必要はなく、変更が必要なもののみ記述します。

例えば、app/config/app.php はデフォルトのままの場合、app/config/local/app.php では下記のように記述します。

この設定では、app.phpdebugprovider について変更を行っています。debugtrue に変更しています。providersでは、デフォルトの値は全て有効にして、追加のみ行ないたいので、append_config関数で追加する ServiceProvider のみ指定しています。

このように変更差分にのみ記述することで、最小限の記述で環境ごとに設定値を変えることができます。

<?php

return [
    'debug' => true,
    'providers' =>  append_config([
        'BarryvdhLaravelIdeHelperIdeHelperServiceProvider',
        'WayGeneratorsGeneratorsServiceProvider',
    ]),
];

利用している環境設定

よく利用している環境設定は以下です。

  • local = Vagrant VM 開発環境用。debug=true、IdeHelper や Generator など開発用 ServiceProvider を組み込む。
  • production = 本番環境用。debug=falseで、開発用 ServiceProvider は除外。暗号キーは、専用のものに。
  • statging = ステージング環境用。ほぼ本番環境で、urlなどを変更。
  • heroku = Heroku環境用。Heroku では、各種アドオンとの接続情報を環境変数から得るので、そのあたりを各設定ファイルに記述。
  • testing = 自動テスト環境用。テスト用データベース設定など。これはフレームワークで予約されており、テスト実行時には自動で指定される。

artisan コマンド

artisan コマンドでも同じフローで環境が決定されるのですが、それとは別に--envオプションで指定することができます。

下記のように local 環境においても、--env=productionを指定すると production 環境で実行することができます。

$ php artisan env
Current application environment: local

$ php artisan env --env=producion
Current application environment: producion

さいごに

Laravel の環境設定について見てみました。

多様な環境について設定を切り替える機構は便利なもので、とても重宝しています。

いまは環境変数での指定に落ち着いていますが、staging などで、artisan コマンド実行時に--envを指定する手間を省くために、.laravel_envのような環境を指定するファイルを用意して、そこに環境設定を記述して、それを読み込むというようなことも考えています。(.laravel_env は .gitignore して、デプロイ時に自動生成する想定。)

.laravel_envがあればそれを使い、無ければ環境変数から読むという流れです。

どのように環境を決定するかということも、アプリケーションで柔軟に変更できるというのも良くできているところですね。

参考

  • コメント (Close): 0
  • トラックバック (Close): 0

AWS EC2 インスタンス間の名前解決に Route 53 を使う

  • 2014-09-05 (金)
  • AWS
この記事の所要時間: 638

Route 53 に EC2 インスタンスの Public DNS を CNAME で登録して、それを EC2 インスタンス間での通信でも利用するという話です。

1. 前提

  • EC2-Classic 環境
  • EC2 インスタンスの接続情報(FQDN なり IP なり)は、AWS のメンテナンスによる再起動などで変更される。
  • アプリケーションやミドルウェアで、別インスタンスに接続している場合、AWS から割り当てられる Public DNS や IP を設定ファイルなどに記述していると、変更の度に修正が必要になる。
  • DNSサーバを立てようとしたが、そこまで変更の頻度は多くない(日常的にインスタンス数が増減するわけではない)ので、正直わざわざ立てるほどでも無い。また、DNS サーバの面倒も見たくない。

2. やりたいこと

  • Route 53 で各ホストの接続情報を管理すれば、一元管理できるし、修正も一箇所で済む。
  • DNS サーバの面倒を見る必要が無いし、自分で運用するより安心。(Route53 は、SLA 100%
  • EC2 インスタンスごとに FQDN を割り当てて、CNAME として EC2 インスタンスの Public DNS を設定する。
  • Public DNS を設定するのは、同じ FQDN で、AWS 外部からはグローバル IP、内部ではプライベート IP を返せるようにするため。
  • 外部からのアクセスは、Security Group で制限する。

3. 設定

3-1. Route 53 で、サブドメインを作る

まず、EC2 インスタンス用のサブドメインを作成します。これは FQDN の管理の都合上だけなので、すでに存在してるドメインに、CNAME レコードを追加しても問題無いです。

ここでは、example.com を保持しているとして、サブドメインとして aws.example.com を作成します。EC2 インスタンスは、web1.aws.example.com や db-master.aws.example.com などにします。

まず、Route 53 の画面で、「Create Hosted Zone」をクリックして、新しいゾーンを作成します。Domain Nameには今回作成するサブドメインを記述します。

route53_create_zone

ゾーンを作成すると、Delegation Set が割り当てられます。これは後で、委譲先として設定するのでコピーしておきます。

route53_delegation_set

aws.example.com をサブドメインとして設定します。ここでは、example.com ドメインを Route 53 で管理している想定なので、それ以外の場合は、それぞれ適時設定して下さい。

すでにある exaple.com ゾーンを開いて、「Create Record Set」をクリックして、新しいレコードセットを作成します。画面右側のフォームで、「Nameaws を、TypeNS - Name server を入力します。Value には、先ほどコピーしておいた aws.example.com ゾーンの Delegation Set の内容をペーストします。

route53_ns_record

これで aws.example.com の設定ができました。

3-2. Route 53 で、EC2 インスタンスの FQDN を設定する

あとは、作成した aws.example.com に、レコードセットを追加して、EC2 インスタンスの Public DNS を CNAME として登録していくだけです。

ここでは、Web サーバとして使っている EC2 インスタンスの Public DNS を、web1.aws.example.com に割り当てます。

まず、EC2 の Public DNS を確認します。Management Console では下記のように表示されているので、これをコピーしておきます。

ec2_public_dns.png

次に、Route 53 で、aws.example.com ゾーンを選択して、「Create Record Set」をクリックします。フォームには、以下のように、Nameweb1TypeCANE - Canonical nameValue に先ほどコピーした EC2 インスタンスの Public DNS を設定します。

ec2_public_dns

これで設定は完了です。

3-3. 動作確認

設定した FQDN が引けるかどうか確認します。(実際は、実在の FQDN で実行してますが、ここでは例示のため、exmaple.com ドメインとしています。)

まず、EC2 インスタンス内で引いてみます。こちらでは、10.0.yyy.yyy というローカル IP が引けました。

[ec2-user@ip-10-xxx-xxx-xxx]$ dig web1.aws.example.com
;; ANSWER SECTION:
web1.aws.example.com.    300     IN      CNAME   ec2-54-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com.
ec2-54-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com. 60 IN A 10.0.yyy.yyy

次に、AWS の外部で引いてみます。54.yyy.yyy.yyy というグローバル IP が引けました。

$ dig web1.aws.example.com
(snip)
;; ANSWER SECTION:
web1.aws.example.com.    300     IN      CNAME   ec2-54-xxx-xxx-x.ap-northeast-1.compute.amazonaws.com.
ec2-54-xxx-xxx-x.ap-northeast-1.compute.amazonaws.com. 604800 IN A 54.yyy.yyy.yyy

どちらも正常に動作していることが確認できました。

4. 利用

アプリケーションやミドルウェアなどで、EC2 インスタンスへ接続する場合は、今回設定した web1.aws.example.com を設定します。AWS 内部であれば、ローカル IP が引けるので、内部ネットワークで接続できます。

動作確認などで、外部から接続する場合も同じく web1.aws.example.com へ接続します。AWS 外部であれば、グローバル IP が引けるので、該当インスタンスへ接続することができます。

5. Public DNS が変更した場合

EC2 インスタンスの再起動などで、Public DNS が変更になった場合は、Route 53 にて、web1.aws.example.com の Value を新しいインスタンスの Public DNS に設定するだけです。

さいごに

Route 53 で、EC2 インスタンスの Public DNS を設定する方法を見てきました。

ここでは、EC2 インスタンスの話を書いていますが、RDS や ElastiCache などのエンドポイントも同じように Route 53 で FQDN を割り当てておくと、もしエンドポイントが変更になった際も変更箇所が限定されているので楽です。

ただ、Route 53 に登録するということは、当然ながら、誰もが Public DNS を知ることができるという点は留意しておく必要があります。(もちろん、FQDN も知る必要がありますが)個人的には、Security Group で接続制限をかけていれば問題は無いと思いますが、これまずいんじゃない?というのがあれば、教えて下さい m(_ _)m

  • コメント (Close): 0
  • トラックバック (Close): 0

Home > アーカイブ > 2014-09

検索
フィード
メタ情報

Return to page top