Amazon Web Services ブログ

サーバーレス LAMP スタック – Part 4: サーバーレス Laravel アプリの構築

本投稿は AWS サーバーレス アプリケーションのシニアデベロッパーアドボケートである Benjamin Smith による寄稿です。

本シリーズの他のパートは以下のリンクからアクセスできます。また、関連するサンプルコードはこちらの GitHub リポジトリにあります。


この投稿では、サーバーレスアプローチで Laravel アプリケーションをデプロイする方法を学びます。
これは「サーバーレス LAMP スタック」シリーズの4番目の投稿になります。過去の投稿はこちらです。

Laravel は PHP 用のオープンソースの Web アプリケーションフレームワークです。フレームワークを使用すると、開発者は一般的なコンポーネントとモジュールを再利用することで、より速く構築できます。また、開発標準に準拠することにより、長期的なメンテナンスにも役立ちます。ただし、従来の LAMP スタックを使用して PHP フレームワークをスケーリングする場合は、まだ課題があります。サーバーレスアプローチを使用してフレームワークをデプロイすると、これらの課題の解決に役立ちます。

Laravel アプリケーションのサーバーレスインフラストラクチャへの展開を簡素化する方法は数多くあります。ここで紹介する方法では、AWSサーバーレスアプリケーションモデル(AWS SAM)テンプレートを使用しています。これによって、Laravel アプリケーションが単一の Lambda 関数にデプロイされます。この関数は、Bref FPM カスタムランタイムレイヤーを使用して PHP を実行します。AWS SAMテンプレートは、「サーバーレス LAMP スタック – パート3: Webサーバーの置き換え」で詳細に説明されている次のアーキテクチャをデプロイします。

サーバーレス LAMP スタック

AWS SAM を使用した Laravel と Bref のデプロイ

Composer は、PHP の依存関係管理ツールです。プロジェクトライブラリと、Laravel や Bref などの依存関係を宣言して管理できます。

次の手順を使用して、AWS SAM で Laravel と Bref をデプロイします:

  1. Composer を使用してLaravel インストーラをダウンロードします。
     composer global require Laravel/installer
  2. Laravel をインストールします。
     composer create-project --prefer-dist laravel/laravel blog
  3. Laravel プロジェクトで、Composer を使用して Bref をインストールします。
     composer require bref/laravel-bridge
  4. アプリケーションのルートディレクトリで AWS SAMテンプレートのクローンを作成します。
     git clone https://github.com/aws-samples/php-examples-for-aws-lambda/
  5. ディレクトリを「0.4-Building-A-Serverless-Laravel-App-With-AWS-SAM」に変更します。
     cd 0.4-Building-A-Serverless-Laravel-App-With-AWS-SAM
  6. AWS SAM CLI のガイド付きデプロイを使用してアプリケーションをデプロイします。
     sam deploy -g

AWS SAM がアプリケーションをデプロイすると、Amazon CloudFront ディストリビューションのドメイン名が返されます。このディストリビューションからサーバーレス Laravel アプリケーションへアクセスできます。

AWS SAM テンプレートの結果の CloudFront ドメイン名

Lambda 向けの Laravel の設定

Laravel を Lambda 関数で実行するには、いくつかの構成変更が必要です。

セッションデータストア

Lambda インスタンスには 512 MB の一時ディレクトリ(ファイルシステム)が含まれていますが、これは耐久性のあるストレージ向けではない一時的なリソースです。これは、関数呼び出しごとに同じ Lambda インスタンスが再利用される保証がないためです。

このため、Laravel セッションデータが必要な場合は、Lambda 関数の外部に保存する必要があります。サーバーレスアプリケーションで状態を管理するために利用できるさまざまなオプションがあります。この場合、セッションデータをデータベースに保存するか、ブラウザの Cookie を使用することをお勧めします。

Laravel の .env ファイルを更新し、session_drivercookie を設定定します。

 SESSION_DRIVER=cookie

ロギング

Laravel は、Monolog と呼ばれる PHP ロギングライブラリを実装しており、多くの宛先にログを書き込むことができます。Laravel Monolog は  log channels  によってこれらの宛先を指定します。各チャネルは、 /config/logging.php ファイル内で連想配列として定義されています。

Lambda インスタンスのファイルシステムは複数の Lambda 関数呼び出し間で共有されないため、アプリケーションログは Amazon CloudWatch Logs などの外部の中央の場所に書き込むことが望ましいです。PHP によって発行されるすべてのエラー、警告、および通知は、CloudWatch Logs に転送されます。これにより、単一の場所から将来の分析のためにログを簡単に表示、検索、フィルタリング、またはアーカイブできます。これを設定するには、Laravel .env ファイルに以下を追加します。

 LOG_CHANNEL=stderr

これにより、stderr チャネルがすべてのアプリケーションログを書き込むために使用されることが保証され、それは CloudWatch Logs に自動的に転送されます。このチャネルは /config/logging.php で定義されています:

'stderr' => 
    [ 
    'driver' => 'monolog', 
    'handler' => StreamHandler::class, 
    'formatter' => env('LOG_STDERR_FORMATTER'), 
    'with' => [ 
        'stream' => 'php://stderr', 
    ], 
],

単一の Lambda 呼び出しに対する CloudWatch Logs

コンパイルされたビュー

ビューには、アプリケーションによって提供されるHTMLが含まれ、アプリケーションロジックとプレゼンテーションロジックが分離されます。デフォルトでは、ビューはアプリケーションの storage ディレクトリ内でオンデマンドでコンパイルされます。

Lambda にはストレージディレクトリへの書き込みアクセス権がないため、関数が /tmp ディレクトリにビューを書き込むように Laravel を設定する必要があります。これは、各 HTTP リクエストの期間中にのみ必要な一時データ用の一時ファイルシステムです。

.env ファイルに次の行を追加して、コンパイルされたビューのために新しいディレクトリパスを使用するように Laravel を設定します。

 VIEW_COMPILED_PATH=/tmp/storage/framework/views

Laravel はアプリケーションへのコンポーネントの登録または「ブートストラップ」のためにに service providers を使用します。AppServiceProvider.php ファイルは、すべてのビューで共有されるデータのための中心的な場所です。次のコードを Providers/AppServiceProvider.php ファイルに追加します。

public function boot() { 
    // Make sure the directory for compiled views exist 
    if (! is_dir(config('view.compiled'))) { 
        mkdir(config('view.compiled'), 0755, true); 
    } 
}

これにより、ビューディレクトリが存在しない場合は、Lambda 関数の呼び出しごとにビューディレクトリが自動的に作成されます。

Amazon S3 によるファイルシステムの抽象化

Laravel は Flysystem と呼ばれる ファイルシステム抽象化 パッケージを使用しています。これにより、ファイルシステムの場所を構成するための単純なドライバーメカニズムが提供されます。Lambdaの /tmp ディレクトリは一時的なものであるため、ファイルシステムの場所は Lambda 関数の外部にある必要があります。次の行を  .env ファイルに追加して、Amazon S3 ファイルシステムドライバーを使用するように Laravel を設定します。

 FILESYSTEM_DRIVER=s3

AWS SAM テンプレートによって、これらのオブジェクトを保存するための S3 バケットをデプロイできます。

Storage:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: php-example-laravel-FileSystemBucket

バケット名は、AWS SAM テンプレート内から環境変数として Lambda 関数に提供されます。

    Environment:
      Variables:
        AWS_BUCKET: !Ref Storage

Lambda 関数には、IAM ポリシー定義を使用して、S3 バケットへの読み取り/書き込み権限が付与されます。

Policies:
        - S3FullAccessPolicy:
            BucketName: !Ref Storage

Laravel のファイルシステム構成は config/filesystems.php で指定します。ここで AWS SAM 環境変数を使用して S3 ファイルシステムディスクを定義します。

's3' => [
            'driver' => 's3',
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'token' => env('AWS_SESSION_TOKEN'),
            'region' => env('AWS_DEFAULT_REGION'),
            'bucket' => env('AWS_BUCKET'),
            'url' => env('AWS_URL'),
            'endpoint' => env('AWS_ENDPOINT'),
        ],

AWS アカウント情報とバケット ARN は、Laravel の env() 関数を使用して、PHP を実行している Lambda 環境から取得できます。

パブリックなアセットファイル

Laravel には、画像や CSS ファイルなどのように、パブリックにアクセス可能なファイルを格納するためのパブリックディスクドライバーがあります。デフォルトでは、パブリックディスクドライバーはこれらのファイルを storage/app/public/ に保存するよう構成されています。これらのファイルは S3 に保存する必要があります。このため、config/filesystems.php の構成を次のように変更します。

'public' => env('FILESYSTEM_DRIVER_PUBLIC', 'public_local'),
'disks' => [
    'local' => [
        'driver' => 'local',
        'root' => storage_path('app'),
    ],

    'public_local' => [
        'driver' => 'local',
        'root' => storage_path('app/public'),
        'url' => env('APP_URL').'/storage',
        'visibility' => 'public',
    ],
    's3' => [
        'driver' => 's3',
        'key' => env('AWS_ACCESS_KEY_ID'),
        'secret' => env('AWS_SECRET_ACCESS_KEY'),
        'token' => env('AWS_SESSION_TOKEN'),
        'region' => env('AWS_DEFAULT_REGION'),
        'bucket' => env('AWS_BUCKET'),
        'url' => env('AWS_URL'),
        'endpoint' => env('AWS_ENDPOINT'),
    ],
    's3_public' => [
        'driver' => 's3', 
        'key' => env('AWS_ACCESS_KEY_ID'), 
        'secret' => env('AWS_SECRET_ACCESS_KEY'), 
        'token' => env('AWS_SESSION_TOKEN'), 
        'region' => env('AWS_DEFAULT_REGION'), 
        'bucket' => env('AWS_PUBLIC_BUCKET'), 
        'url' => env('AWS_URL'), 
    ],
],

これにより、S3ドライバーを使用する s3_public という名前の新しいファイルシステムディスクが追加されます。Laravel のenv() 関数が環境変数 env( ‘AWS_PUBLIC_BUCKET’ ) を取得して、バケットの場所を設定/構成します。バケット名は環境変数として Lambda 関数に渡されます。

次の行を env ファイルに追加して S3 を使用するようにパブリックディスクを構成します:

 FILESYSTEM_DRIVER_PUBLIC=s3

ビューテンプレートでの静的アセットの参照

Laravel の asset() ヘルパー関数では、リクエストの現在の URL スキーム(HTTPまたはHTTPS)を使用してアセットの URL を生成できます。

$url = asset('img/photo.jpg');

これらのアセット自体は S3 に保存されることで CloudFront のグローバル CDN を介して提供可能になります。.env ファイルで ASSET_URL 変数を設定して、URL ホストを構成します。

ASSET_URL=https://{YourCloudFrontDomain}.cloudfront.net

これにより、アプリケーションは CloudFront ドメインを介して S3 のアセットを正しく参照できます。Laravel のネイティブ asset() ヘルパー関数は、次の形式でビューテンプレート内から使用されます。

<img src="{{ asset('assets/icons.png') }}">

Lambda を使用したサーバーレス Laravel アプリ

補足: サーバーレス Laravel アプリケーションのデプロイ

  1. Bref、PHP 用のオープンソースのカスタムランタイム。最近 新たなプルリクエストをマージし、Lambda 向けに自動で Laravelを構成できるようになりました。この新しいパッケージでは、Amazon SQS を Laravel キュージョブシステムと統合する方法も提供しています。
  2. Laravel Vapor : Laravel のサーバーレスデプロイプラットフォームです。これは、AWSクラウド上で Laravel チームによって構築された有料サービスです。

まとめ

この投稿では、AWS SAM やサーバーレスアプローチを使用して PHP Laravel アプリケーションをデプロイする方法について説明しました。S3 で外部ファイルシステムと静的アセットを使用してセッションストアと集中ロギングを実装するために必要な初期 Laravel 構成手順について説明しました。

PHP開発チームは、ビルド方法を変更することなく、コードの配布に集中できます。さあ、PHP を使用してサーバーレスアプリケーションの構築を開始しましょう。

付随するコードと手順については、この GitHubリポジトリにアクセスしてください。

原文はこちらです。