”AWS Lambda で Laravel を動かしてみた”をやってみた
と
リクガメのおウチの温度/湿度をモニターしてawsに投げるのを1000円くらいでやる on arduino
の続編的なやつです
センサーデータがdynamodbにガシガシ入ってきてるので、それをフロントで見えるようにしましょう。
環境
- Amazon Linux 2(ec2) Linux 4.14.88-88.73.amzn2.x86_64
- php7.2
- laravel 5.7.19
- aws lambda + lambda layer + api gateway
前回、/var/task
にlaravel一式を置いてしまいました。lambda layerのパッケージ落としてきてlocalでdocker runみたいな事ができたらいいんだけど、ひと手間ふた手間じゃできなそうだ。
ローカルでartisan serveして開発すすめよう。
というわけで、ec2にポート8000番を通してやります。念のため自分のIPアドレスだけ通すように。
なお、この前作ったスポットインスタンス。

**Saving71%**ですってよ奥さん。こんなお買い得なのか。
・・ちょっと脱線しちゃいました。
ポート8000番だ。セキュリティグループに自分用に22番空けてるやつがあったのでそこに追加しました。

そしてec2の/var/task
でphp artisan serve -host 0.0.0.0 &
ってやったらブラウザでlaravel見れました。
Dynamodb
まずはDynamodb使うとこからいきましょうか。
ここが参考になる。
まずはbaopham/laravel-dynamodb
$ composer require baopham/dynamodb
$ vi config/app.php <- 'providers'に追加
$ php artisan vendor:publish
Which provider or tag's files would you like to publish?:
[0 ] Publish files from all providers and tags listed below
[1 ] Provider: BaoPham\DynamoDb\DynamoDbServiceProvider
[2 ] Provider: BeyondCode\DumpServer\DumpServerServiceProvider
[3 ] Provider: Fideloper\Proxy\TrustedProxyServiceProvider
[4 ] Provider: Illuminate\Foundation\Providers\FoundationServiceProvider
[5 ] Provider: Illuminate\Mail\MailServiceProvider
[6 ] Provider: Illuminate\Notifications\NotificationServiceProvider
[7 ] Provider: Illuminate\Pagination\PaginationServiceProvider
[8 ] Provider: Laravel\Tinker\TinkerServiceProvider
[9 ] Tag: config
[10] Tag: laravel-errors
[11] Tag: laravel-mail
[12] Tag: laravel-notifications
[13] Tag: laravel-pagination
> 1
Copied File [/vendor/baopham/dynamodb/config/dynamodb.php] To [/config/dynamodb.php]
Publishing complete.
.envに下記を追記します。
$ echo DYNAMODB_CONNECTION='"${DYNAMODB_CONNECTION}"' >> .env
$ echo DYNAMODB_KEY='"${DYNAMODB_KEY}"' >> .env
$ echo DYNAMODB_SECRET='"${DYNAMODB_SECRET}"' >> .env
$ echo DYNAMODB_DEBUG='"${DYNAMODB_DEBUG}"' >> .env
$ echo DYNAMODB_REGION="ap-northeast-1" >> .env
今回の環境はec2でiamロール設定済なのでこうします
$ export DYNAMODB_CONNECTION=aws_iam_role
labmdaの時はアクセスキー認証にしようかな。
ページ追加
一回接続の確認したいのでcontrollerとかmodelとか作ります。
$ php artisan make:controller Dht22Controller
$ php artisan make:model Models/Dht22
下記のviewとmodelを作ります。
<h1>{{ $title }}</h1>
<p>{{ $body }}</p>
<?php
namespace App\Models;
use Baopham\DynamoDb\DynamoDbModel as Model;
class Dht22 extends Model
{
protected $table = 'kamekusa_dht22';
protected $primaryKey = 'id';
protected $compositeKey = ['id', 'expire'];
public $timestamps = false;
protected $fillable = [
'id',
'expire',
'payload',
];
}
<?php
Route::get('/', function () { return view('welcome'); });
Route::get('/dht22', 'Dht22Controller@index');
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Dht22;
class MonitorController extends Controller
{
public function index()
{
$dht22= new Dht22();
$datas = $dht22->all();
$datas = json_encode($datas);
return view ('dht22.index', ['body' => $datas, 'title' => 'Hello Lambda on Laravel with Dynamo!']);
}
}
こうなりました。
ただ、$dht22->all();ってやると/vendor/aws/aws-sdk-php/src/DynamoDb/Marshaler.php
のunmarshalValueのとこでDeprecated: The each() function is deprecated. This message will be suppressed on further calls
って出て困ったので取り急ぎforeachに置き換えました。
eachはphp7.2から非推奨なんですね。ホストはphp7.2にしてたのでちょうどひっかかったか。
というか今、最新のソース見たら直ってました。
Vue.js
ではお次はVue.js。
最短でやりたいです。
sudo amazon-linux-extras install epel
sudo yum install -y nodejs
$ node --version
v6.14.3
$ npm --version
3.10.10
おもむろにnodejsをいれてみる。ちょっと古い気がするけどどうしたもんか。とりあえず進めてみるが、npm install
は無事完了。
で、最短でやるやつのレポジトリを参考にさせていただきつつ進め、なんとか表示はできました。細かい所は適当ですが。
ちゃんと日付順に並べてグラフ出したりはしたいけどひとまずはここまでで。
vueのcomponentsはこんな感じになりました。最低限な感じですが。
<template>
<div class="container">
<div class="row">
<div class="col-md-12 jumbotron">
<h1>温度と湿度を表示するLambda on Laravel</h1>
</div>
</div>
<div class="row">
<div class="col-md-12 float-right">
<div class="gtn-group">
<span class="group-btn">
<button class="btn btn-success" type="button" @click="getAll()">読みこむ </button>
</span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th>id</th>
<th>expire</th>
<th>温度</th>
<th>湿度</th>
</tr>
</thead>
<tbody>
<tr v-for="data in datas" v-bind:key="data.id">
<td>{{data.id}}</td>
<td>{{data.expire | moment("YYYY/MM/DD h:mm:ss a")}}</td>
<td>{{data.d1}}℃</td>
<td>{{data.d2}}%</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<script>
Vue.use(require('vue-moment'));
export default {
data(){
return {
datas: []
}
},
methods:{
getAll: function () {
axios.get('/api/dht22').then((res)=>{
let _datas = res.data
this.datas=[]
for (let d of _datas) {
if ('payload' in d){
console.log(d.payload);
this.datas.push(d.payload)
}
}
})
}
},
created(){
const self = this
self.getAll()
setInterval(function() {self.getAll()}, 60*1000)
}
}
</script>
その他のソース。
https://github.com/ikegam1/Lambda-on-Laravel-on-VueJs-with-Dynamodb
Lambda
最後にLambdaに上げる。
npm run prod
して、sam cli叩いてさくっと終わるつもりが・・
おうふ。。そっかcssとかjsとかlambda経由じゃアクセスできんな。。cloudfront噛まつつ、S3に静的コンテンツ上げて振り分けて、ってやんないといけないのかな。でもまあそこまでしてlaravelでやる必要もないような。。
というわけでとりあえず動くところまではやる。
やったこと。
- public/css/app.cssをwelcome.blade.phpにインラインで埋め込んだ
- public/js/app.jsをwelcome.blade.phpにインラインで埋め込んだ
- api/dht22のパスを/Prod/api/dht22に直した
- api gatewayでapiリソースとその配下にdht22リソース作った
- sam cli用のtemplate.ymlにDYNAMODB_KEYとかのenvironmentを追記した

というわけでなんとか動きました!ギリギリサーバレスです。