以前構築したサービスのフレームワークはPhalconだったのだが、
PHP7への対応が遅かったり、今後のメンテナンスでどうなるのか不安なので、他のフレームワークも試そうと思った。
一からマイクロサービスの開発フローを作った話
ためしにLaravelと、Laravel製の軽量フレームワークLumenを試した。
今回、LaravelとLumenを試したが、Laravelのインストールするだけでほぼ動作したのに対し、Lumen側では一部ハマりどころがあったので、Lumenのインストール方法と連携からメモしていく。
コードは以下に公開してある。
https://github.com/tomoyamachi/lumen-docker-sample
versions
- PHP : v7.1.*
- MySQL : v5.6.*
- Redis : v3.0.*
- Lumen : v5.2.* : プロジェクトは独立しているので置き換え可能
最終フォルダ構成
.
├── docker-compose.yml # docker-compose用
├── deploy # docker各コンテナ設定用
├── features # APIテスト用(cucumber)
└── sample # サンプルアプリ用ファイル一式
├── app
│ ├── Console
│ ├── Events
│ ├── Exceptions
│ ├── Http
│ │ ├── Controllers # コントローラを保存
│ │ ├── Middleware
│ │ └── routes.php # ルーター
│ ├── Jobs
│ ├── Listeners
│ ├── Providers
│ └── User.php # モデル
├── artisan
├── bootstrap # 起動時に読み込むパッケージなどを指定
├── composer.json
├── composer.lock
├── database
│ ├── factories
│ ├── migrations # マイグレーションファイル
│ └── seeds
├── phpunit.xml
├── public
├── resources
├── storage
│ └── logs
│ └── lumen.log # log出力先
├── tests # テストファイル
└── vendor
Lumenの導入
公式サイトの通りにインストール。
$ composer global require "laravel/lumen-installer"
フォルダ内でプロジェクト作成
$ mkdir lumen-docker-sample && cd lumen-docker-sample
$ composer create-project --prefer-dist laravel/lumen sample
...lumenプロジェクト作成...
docker-composeの設定
docker-compose.ymlの作成
プロジェクトのルートディレクトリにdocker-compose.ymlとコンテナ設定用のファイルを作成する。今回はdeployフォルダ内に各種dockerfileを置いた。
version: '2'
services:
web:
build:
context: ./
dockerfile: deploy/web.docker
volumes:
- ./:/var/www
ports:
- "8080:80"
links:
- app
app:
build:
context: ./
dockerfile: deploy/app.docker
volumes:
- ./:/var/www
links:
- database
- cache
environment:
- "DB_PORT=3306"
- "DB_HOST=database"
- "REDIS_PORT=6379"
- "REDIS_HOST=cache"
database:
image: mysql:5.6
environment:
- "MYSQL_ROOT_PASSWORD=sample_pass"
- "MYSQL_DATABASE=sample_db"
ports:
- "33061:3306"
cache:
image: redis:3.0
ports:
- "63791:6379"
queue:
build:
context: ./
dockerfile: deploy/queue.docker
volumes:
- ./:/var/www
links:
- database
environment:
- "DB_PORT=3306"
- "DB_HOST=database"
コンテナ起動
$ docker-compose up -d # docker-composeした環境をバックグラウンドで走らせる
Creating network "lumendocker_default" with the default driver
Creating lumendocker_cache_1
Creating lumendocker_database_1
Creating lumendocker_app_1
Creating lumendocker_web_1
Creating lumendocker_queue_1
動作確認
docker-machineを利用しており、defaultという名前で登録している前提で記載する。
docker-composeファイルで設定した8080ポートに通信ができるかを確認。
$ curl $(docker-machine ip default):8080
Lumen (5.2.8) (Laravel Components 5.2.*) # OK
アプリケーションの開発
MySQLとの紐付け
LumenはLaravelのライブラリを最低限しか読まないことで軽量化しているが、ORMやRedisとの連携を取ろうとすると、読み込まないように設定してあるライブラリを読み込む必要がある。
LaravelのModelを利用したい場合、bootstrap/app.phpで以下のコメントアウトを外す。
$app->withEloquent();
また、.envファイルに、docker-compose.ymlファイルで指定したMySQLの設定を記載する。
DB_CONNECTION=mysql
DB_HOST=192.168.99.100
DB_PORT=33061
DB_DATABASE=sample_db
DB_USERNAME=root
DB_PASSWORD=sample_pass
Redisとの紐付け
同じくライブラリを読み込む設定をする。また、必要なパッケージをcomposerから取得する
"require": {
"php": ">=7.0.10",
"laravel/lumen-framework": "5.2.*",
"vlucas/phpdotenv": "~2.2",
// ここを追加
"illuminate/redis": "5.2.*",
"predis/predis": "~1.0"
},
bootstrap.appで読み込むライブラリなどを設定。
$app->withFacades(); // コメントアウトする
$app->register(Illuminate\Redis\RedisServiceProvider::class); //プロバイダにRedisのクラスを追加
同じく.envファイルにredisの接続先情報を追加。
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_DRIVER=sync
REDIS_HOST=192.168.99.100
REDIS_PASSWORD=null
REDIS_PORT=63791
ユーザの名前を保存と取得をするAPIを作る
テーブルの作成
まずphp artisan make:migration create_user
で、migrationファイルを作成し、テーブル構造を記入。
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class User extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('users');
}
}
テーブルを作成する。
$ php artisan migrate
Migration table created successfully.
Migrated: xxxxx_create_user
routesの設定
インターフェースを決める。
$app->post('users', 'UserController@create'); // ユーザの作成
$app->get('users/{id}', 'UserController@get'); // ユーザの取得
Controllerの作成
むりやりMySQLとRedisを併用する。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redis;
class UserController extends Controller
{
public function create(Request $request)
{
$name = $request->input('name');
if (empty($name)) {
return 'invalid name';
}
$user = new \App\User();
$user->name = $name;
if ($user->save()) {
// redisにユーザ情報を保存
Redis::set('user:profile:'.$user->id, $user);
return 'success';
}
return 'failed';
}
public function get(Request $request, $id)
{
$cacheResult = Redis::get('user:profile:'.$id);
// redisキャッシュがあればキャッシュから
if ($cacheResult) {
return $cacheResult;
}
// なければDBから取得
return \App\User::findOrFail($id);
}
}
モデルを作成
特にこったことはしないので、Eloquent\Modelを継承するだけでいい。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
}
動作確認
$ curl -X POST -F "name=test" http://$(docker-machine ip default):8080/users
success
$ curl $(docker-machine ip default):8080/users/1 | jq
{
"name": "test",
"updated_at": "2016-08-26 09:36:37",
"created_at": "2016-08-26 09:36:37",
"id": 1
}
その他
単体テスト
phpunitがデフォルトでcomposerの中に含まれているので、phpunitコマンドでテストできる。
vendor/bin/phpunit
PHPUnit 4.8.27 by Sebastian Bergmann and contributors.
.
Time: 231 ms, Memory: 7.00MB
OK (1 test, 1 assertion)
結合テスト
同じくphpunitでテスト可能らしいが、まだ試していない。
https://lumen.laravel.com/docs/5.2/testing#application-testing
今後のこと
Lumenを今後の開発で利用するかは分からないが、確かに最低限の機能という感じで印象がいい。あとはWerckerCIと連携して色々やりたい。