page_adsence

2015年12月28日月曜日

Laravel4系のパッケージ作成における設定ファイルの読み込み

Laravelでcomoserで管理する自作ライブラリを作成していたのですが、どうしても設定ファイルが読み込めないという事態があった。

下記の様な形で設定ファイルを置いてみたのですが、いくらやってもNULL。
app/config/packages/vendor_name/package_name/config.php
app/config/packages/vendor_name/package_name/test.php

色々調べて見ると、原因はパッケージ側に設定ファイルがない事が原因でした。
vendor/vendor_name/package_name/src/vendor_namespace/config/config.php
vendor/vendor_name/package_name/src/vendor_namespace/config/test.php

どうやらパッケージ側の設定ファイルの値を、アプリ側の設定ファイルの値で上書きするような挙動になっているようです。 使用する場合は、
Config::get('package_name::filename.key')


例えば、下記の様な設定ファイルがあるとする。
$ vi vendor/vendor_name/package_name/src/vendor_namespace/config/test.php
<?php
return array(

    'key' => 'testtest'

);
$ vi app/config/packages/vendor_name/package_name/test.php
<?php
return array(

    'key' => 'testtesttest'

);


このファイルの内容を取得する場合は、
Config::get('package_name::test.key'); → 結果:testtesttest
設定ファイル名がconfig.phpで、アプリ側に設定ファイルがなかった場合
$ vi vendor/vendor_name/package_name/src/vendor_namespace/config/config.php
<?php
return array(

    'key' => 'testtest'

);
app/config/packages/vendor_name/package_name/config.php ← このファイルはない
このファイルの内容を取得する場合は、
Config::get('package_name::key'); → 結果:testtest

Dockerを使って開発環境を整えてみた

今まで自分の開発環境はWindows7 + Cygwin + Vagrant + Ansible + VirtualBoxで作っていたのですが、
マシンスペックの都合上、複数台のVMを動かすのが厳しくなってきたので、Dockerを使って開発環境を構築してみようと思います。
また、DockerHubからイメージを落としてくるのではなく、自分で1からDockerfileを作っていこうと思います。
とりあえず1コンテナにつき1つのミドルウェアのみインストールするようにしました。
また、ベースOSはすべてCentOS6.7にしました。

今回構築したい環境は下記のような感じです。
・ミドルウェア
  - Nginx 1.8.0(LB) × 1台
  - Nginx 1.8.0 × 2台
  - PHP 5.6系
  - MySQL 5.5系
  - HAProxy 1.5系
  - Redis 3.0.5 × 3台(master 1台、slave 2台)
  - Redis-Sentinel × 3台

・構成図


まず、それぞれのDockerfileから作成していきます。
Dockerfileの作成手順としては、下記の様な感じで作っていきました。

1.ベースイメージを取得
$ docker pull centos:6.7
2.ベースのイメージからコンテナを作成してコンテナ内部に入る
$ docker run -it centos:6.7 bash
3.コンテナ内部で、Dockerfileに書きたい内容を一通り試す

4.コンテナから出る
# exit
5.Dockerfileに書く

6.buildしてみる
docker build -t [IMAGE_NAME] PATH
7.成功したらデーモンモードで起動させる。
docker run -d [IMAGE]
8.失敗した場合はログを確認する
docker logs [CONTAINER]


上記の手順で作成したDockerfileは下記にあげてあります。
但し、解説用に編集したDockerfileなので、そのままの状態では使用出来ないので予めご了承下さい。

https://github.com/gyagya/Dockerfiles


続いては、このDockerfileを使って、イメージを作成していきます。
docker build -t image_name Dockerfile

作成したイメージの一覧を確認します。
$ docker images
REPOSITORY           TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
php                  latest              ab774aab6741        2 days ago          477.8 MB
nginx                latest              3cb45e85b756        4 days ago          474.2 MB
nginx-lb             latest              c0e293e58e56        5 days ago          474.1 MB
mysql-data-storage   latest              85e7b48d7503        5 days ago          190.6 MB
mysql                latest              528877b6d10d        5 days ago          781.2 MB
haproxy              latest              8171746ff33b        5 days ago          473.9 MB
redis-sentinel       latest              d90eb8fa284b        5 days ago          503.4 MB
redis-slave          latest              7b0ca34ff4b7        5 days ago          503.4 MB
redis-data-storage   latest              518bace5a446        5 days ago          190.6 MB
redis                latest              23c44601fccd        5 days ago          503.4 MB
file-storage         latest              ab96aa28dc9e        5 days ago          190.6 MB
centos               centos6.7           3fba1048142f        8 weeks ago         190.6 MB

ここまで揃った段階で、docker-composeを使用してまとめてコンテナを起動させます。
docker-composeのインストール方法は下記の通りです。
$ sudo curl -L https://github.com/docker/compose/releases/download/1.4.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
インストールが完了したらdocker-compose.ymlがあるディレクトリか、その配下のディレクトリで
$ docker-compose up -d
で起動ができます。
起動しているかどうかを確認する。
$ docker-compose ps
ここまで完了すれば環境構築は完了です。

■Dockerfileを作成するにあたっての注意点が幾つか。
1.Dockerは何かしらがフォアグラウンドで起動していないと、コンテナを起動させてもすぐに終了してしまいます。
2.資源の節約という意味で、Dockerfileはなるべく容量を少なくする必要が有ります。
下記2つのイメージは同じ内容のコンテナで、Dockerfileの書き方を変えただけのものになります。
$ docker images
REPOSITORY             TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
mysql-mroonga2         latest              697b08894cce        29 seconds ago      781.2 MB
mysql-mroonga          latest              945337cb1dc4        12 hours ago        1.242 GB
何が違うのかというと、容量が少ない方でやった内容はRUNの回数を減らす。yum install後はyum clean allするなどです。
DockerはRUN単位でファイルシステムの更新が走るので、ゴミファイルがあるとその分無駄に差分が発生してしまい、容量の肥大化につながります。

■データの永続化とポータビリティについて
Dockerでデータの永続化をしたコンテナ(MySQLのデータコンテナ等)をexport/saveコマンドとかで持ち運びたいと思ったのですが、これは全く持って出来ません。
永続化(コンテナが停止状態でもファイルはいじれる)は出来ます。
コンテナのexportするとコンテナ自体は移動出来ます。
但し、中身のデータは一切移動出来ません。
おそらく将来的にも出来る様になることはないと思います。
Dockerはあくまで環境のポータビリティを上げるだけで、データのポータビリティを上げるためのツールではないからっていうことなのかもしれません。

■ファイルのマウントに関して 現状使用しているdocker1.7系では、ファイルのマウントはホスト側からコンテナ側にマウントすることしか出来ません。
今回作った環境をDockerをあまり知らない人でも使えるように、コンテナに入らずにログファイルや設定ファイルをいじれる様にしていました。
しかし、ホスト側からコンテナ側にマウントすることしか出来ず、ホスト側で空のディレクトリを用意しておき、設定ファイルが置いてあるディレクトリをマウントしてしまうと、
当然コンテナ側の設定ファイルが消えるので起動しないといった事が有りました。
仕方ないので、コンテナ側と同じファイルをホストマシン上に置いて対応しましたが、設定ファイルを2重管理しないといけないので非常に面倒くさいです。
これはなんとかしたいのですが、今のところ上記の方法でしか解決出来ていません。

Laravel4系のカスタムバリデートの作り方

基本的な作り方に関しては公式サイトに書いてあるのですが、日本語で残しておきたかったので書いておきます。

https://laravel.com/docs/4.2/validation#custom-validation-rules

カスタムバリデータクラスの設置場所は自由で、今回はcomposerで管理する用のライブラリを作成したので、下記のディレクトリに配置しました。
/vendor/vendor_name/package_name/src/vendor_namespace/Validator/CustomValidator.php
<?php namespace TEST\Validator;

class CustomValidator extends \Illuminate\Validation\Validator {

    public function validateTest($attribute, $value, $parameters)
    {
        // バリデート処理
        // OKの場合はtrueを返す
        
        // NGの場合はfalseを返す
    }

    public function replaceTest($message, $attribute, $rule, $parameters)
    {
        // バリデートNGの時に表示するメッセージを編集する
        return $message;
    }

}

元になるルールを作成
$ vi /vendor/vendor_name/package_name/src/vendor_namespace/config/rules.php
<?php
return array(

    // 入力チェック
    'input_rules' => array(
        'name'    => 'required|test',
        'email'   => 'required',
        'message' => 'max:2000',
    ),
);

元になるメッセージを作成
$ vi /vendor/vendor_name/package_name/src/vendor_namespace/config/messages.php
<?php
return array(

    'test' => 'エラーです。',

);

利用する側は下記の様に記述する。
$rules = Config::get('package_name::rules.input_rules');
$messages = Config::get('package_name::messages.test');
$validator = \Validator::make(Input::all(), $rules, $messages);
if ($validator->fails()) {
    var_dump($validator->messages());
}
さらに下記ファイルの最後に追記する。
vi app/start/global.php

/**
 * カスタムバリデータの登録
 */
Validator::resolver(function($translator, $data, $rules, $messages)
{
    return new Test\Validator\CustomValidator(
        $translator, $data, $rules, $messages);
});
以上で使える様になるはず。