36
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PHPAdvent Calendar 2019

Day 16

Brefが進化してたのでサーバーレスLaravel環境作ってみた

Last updated at Posted at 2019-12-16

はじめに

この記事は、PHP Advent Calendar 2019 の16日目の記事です。
PHPerKaigi 2019で『サーバーレスPHP』というお話をさせていただいたのですが、その際に紹介した『Bref』が進化してたので紹介したいと思います。

Brefとは

BrefとはAWS Lambda上でPHPを動作させるためのもろもろの設定を楽にしてくれるCLIです。Brefを利用するためには、AWSアカウント、aws-cliserverless frameworkが必要となります。

いままでのBrefとの変更点

相性の良いサービス

PHPerKaigiでは『DBの絡むものには向いていない』と発表したのですが、現在の公式ドキュメントには

matrix.png
※公式ドキュメントより

上記のように、DBの絡むサービスが相性が良いものに変わっていました。
以前はLambdaからVPCに接続する時のコールドスタートがネックとなるので、相性が悪いサービスとしてDBが絡むものが挙げられてましたが、Lambdaの機能改善により、かなり早くDBにアクセスできるようになりました。よって、RDSを使ったサービスであれば実用に耐えうるものになったようです。

インストール

春先のBrefはこうでした。

composer require mnapoli/bref

が、今のBrefはこう変わっています。

composer require bref/bref

プロジェクト名がわかりやすくなってますね。1点注意ですが、新しいBrefはPHP7.2以上必須です。PHP7.1以下の方はPHPのバージョンアップして再度インストールしてください。

設定ファイル

BrefはデプロイにCloud Fomationを利用するため、Cloud Fomation用の設定ファイルを用意する必要がありました。
例えばこんな感じ。

template.yml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Globals:
  Function:
    Environment:
      Variables:
        APP_ENV: prod

Resources:
  Website:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: 'bref-symfony-website'
      CodeUri: .
      Handler: public/index.php
      Timeout: 30 # in seconds (API Gateway has a timeout of 30 seconds)
      MemorySize: 1024
      Runtime: provided
      Layers:
        - 'arn:aws:lambda:ap-northeast-1:209497400698:layer:php-73-fpm:1'
      Events:
        HttpRoot:
          Type: Api
          Properties:
            Path: /
            Method: ANY
        HttpSubPaths:
          Type: Api
          Properties:
            Path: /{proxy+}
            Method: ANY

  Console:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: 'bref-symfony-console'
      CodeUri: .
      Handler: bin/console
      Timeout: 120 # in seconds
      Runtime: provided
      Layers:
        - 'arn:aws:lambda:ap-northeast-1:209497400698:layer:php-73:1' # PHP
        - 'arn:aws:lambda:ap-northeast-1:209497400698:layer:console:1' # The "console" layer

Outputs:
  DemoApi:
    Description: 'URL of our function in the *Prod* environment'
    Value: !Sub 'https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/'

これは、PHPerKaigiで紹介したBrefを利用して、サーバーレスなSymfony環境を用意するためのCloud Fomation用設定ファイルです。
これでもサンプルがドキュメントに用意してあたので、そんなに問題なく用意できましたが、ぱっと見わかりにくい印象です。
これが、新しいBrefだとこんな感じになります。

serverless.yml
service: bref-symfony-website

provider:
    name: aws
    region: ap-northeast-1
    runtime: provided
    environment:
        # Symfony environment variables
        APP_ENV: prod

plugins:
    - ./vendor/bref/bref

package:
    exclude:
        - node_modules/**
        - tests/**

functions:
    website:
        handler: public/index.php
        timeout: 28 # in seconds (API Gateway has a timeout of 29 seconds)
        layers:
            - ${bref:layer.php-73-fpm}
        events:
            -   http: 'ANY /'
            -   http: 'ANY /{proxy+}'
    console:
        handler: bin/console
        timeout: 120 # in seconds
        layers:
            - ${bref:layer.php-73} # PHP
            - ${bref:layer.console} # The "console" layer

まず、template.ymlというファイル名からserverless.ymlというファイル名に変わり、Cloud Fomation用の設定ファイルでなくserverlessの設定ファイルを用意する形に変更になりました。Cloud Fomationよりもシンプルになったので、かなり書きやすくなったと思います。また、前回同様、公式サイトのドキュメントにサンプルがあるので、それを利用すれば、さくっと設定ファイルが用意できます。

デプロイ

春先では、デプロイは以下のコマンドを入力する必要がありました。

sam package --output-template-file .stack.yaml --s3-bucket [S3バケット名]

sam deploy --template-file .stack.yaml --capabilities CAPABILITY_IAM --stack-name [スタック名]

sam packageで、プロジェクトをS3にアップロードし、sam deployでLambdaにデプロイ、API Gatewayに設定していました。
これが新しいBrefでは

serverless deploy

serverlessのコマンド1つでデプロイできるようになりました。書いてて薄々きづいてきましたが、Brefの進化は、Serverless Frameworkの進化が大きく影響を与えているようです。

Laravel環境をつくってみる。

では、Laravelの環境をセットアップしてみましょう。上記の通りですが、作業をまとめてみると非常にシンプルなのがよくわかります。

インストール

コマンドでインストールしていきます。

composer create-project laravel/laravel serverless-laravel --prefer-dist
cd serverless-laravel
composer require bref/bref
vendor/bin/bref init

 What kind of lambda do you want to create? (you will be able to add more functions later by editing `serverless.yml`) [PHP function]:
  [0] PHP function
  [1] HTTP application
  [2] Console application
 > 1 # どれを選んでもあとで設定を変えるので特に問題ないですが、HTTP applicationを選びました。

Creating serverless.yml
Creating index.php

                                                                                                                        
 [OK] Project initialized and ready to test or deploy.                                                                  
                                                                                                                        

自動生成されたプロジェクト直下のindex.phpは削除しても問題ありません。

serverless設定

そして、serverlessの設定を行います。

serverless.yml
service: serverless-laravel

provider:
  name: aws
  region: ap-northeast-1
  runtime: provided
  environment:
    # Laravel environment variables
    APP_STORAGE: '/tmp'

plugins:
  - ./vendor/bref/bref

functions:
  website:
    handler: public/index.php
    timeout: 28 # in seconds (API Gateway has a timeout of 29 seconds)
    layers:
      - ${bref:layer.php-73-fpm}
    events:
      -   http: 'ANY /'
      -   http: 'ANY /{proxy+}'
  artisan:
    handler: artisan
    timeout: 120 # in seconds
    layers:
      - ${bref:layer.php-73} # PHP
      - ${bref:layer.console} # The "console" layer

regionですが、us-east-1からap-northeast-1に変更しています。この設定はwebsiteとartisanを用意しています。websiteはHTTPアクセス用の設定、artisanはコンソール(後述)の設定です。

Laravel微調整

Lambdaのカスタムランタイム上で動作しますが、/tmpディレクトリをのぞきファイルを保存することができません。そこで、少しLaravelを調整します。
以下のとおり、ファイルを修正します。

bootstrap.php
$app = new Illuminate\Foundation\Application(
    $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);

+ $app->useStoragePath($_ENV['APP_STORAGE'] ?? $app->storagePath());
.env
+ VIEW_COMPILED_PATH=/tmp/storage/framework/views


+ SESSION_DRIVER=array
- SESSION_DRIVER=file


+ LOG_CHANNEL=stderr
- LOG_CHANNEL=stack
app/Providers/AppServiceProvider.php
    public function boot()
    {
+        if (! is_dir(config('view.compiled'))) {
+            mkdir(config('view.compiled'), 0755, true);
        }
    }

デプロイ

ここまで設定したら、デプロイするだけです。

serverless deploy

Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
.... 中略 ....
Serverless: Stack update finished...
Service Information
service: serverless-laravel
stage: dev
region: ap-northeast-1
stack: serverless-laravel-dev
resources: 15
api keys:
  None
endpoints:
  ANY - https://**********.execute-api.ap-northeast-1.amazonaws.com/dev
  ANY - https://**********.execute-api.ap-northeast-1.amazonaws.com/dev/{proxy+}
functions:
  website: serverless-laravel-dev-website
  artisan: serverless-laravel-dev-artisan
layers:
  None
Serverless: Run the "serverless" command to setup monitoring, troubleshooting and testing.

endpointsに記載されてるURLにアクセスしてみましょう。

laravel.png

無事、表示されました。
コンソールも実行できるか確認してみましょう。

vendor/bin/bref cli --region ap-northeast-1  serverless-laravel-dev-artisan -- inspire
Simplicity is the essence of happiness. - Cedric Bledsoe

こちらも動きました。コンソールの設定をすることで、ローカル環境からLambda上のLaravel(artisan)を実行します。serverless.ymlの設定でregionをap-northeast-1に変更したので、bref cliの実行オプションに --region ap-northeast-1を付与します。付与しないとエラーとなるので注意しましょう。

まとめ

PHPerKaigiから約半年ですが、春先よりも随分と設定がシンプルになった印象がしました。前よりも環境が準備しやすいので試しやすく、いろいろなサーバーレスPHPの実例が出てくるような気がします。
来年もPHPerKaigiに参加する予定なので、なにか実例ありましたら是非当日おしえてくださいー!

36
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?