BASEプロダクトチームブログ

ネットショップ作成サービス「BASE ( https://thebase.in )」、ショッピングアプリ「BASE ( https://thebase.in/sp )」のプロダクトチームによるブログです。

AWS LambdaをPHPで
使うためのベストな方法

この記事はBASEアドベントカレンダーの5日目の記事です。 こんにちは!BASEのCRM3チームでバックエンド開発を担当している オリバ(@toshi_oliver)です。2022年11月に入社したので、今回が初のブログとなります。

はじめに

devblog.thebase.in

さて、今回はAWSのサーバレスサービスを代表すると言っても過言ではない、AWS Lambda(以下、Lambda)に関する記事を投稿します。

BASEのバックエンドの大部分はPHPで開発されており、システムの一部にLambdaを使用しているのですが、Lambdaのランタイムでサポートされている言語は以下となっております。

  • Node.js
  • Python
  • Ruby
  • Java
  • Go
  • .NET Core

ご覧の通り、PHPはサポートされておりません。 では、PHPの使用は断念しなければならないのかというとそうではなく、カスタムランタイムを使用することでPHPの使用が可能となります。

しかし、公式ドキュメントを見ると、ランタイム用のbootstrapファイルやシェルファイルを用意し、それをzip化しさらにLambdaレイヤー化する必要があります。

Lambdaはプログラム開発に集中するためのサービスであるにも関わらず、PHPを選択することで手間が増えてしまうのは本末転倒であります。

また、公式ブログによりコンテナイメージを使用する手段もありますが、DockerfileとBootstrapファイルの管理が必要となるため、やや手間が増えます。

そこで、本記事ではLambdaにてPHPのカスタムランタイム環境を簡単に構築できる、brefを紹介します。

前提

  • anyenv(1.1.5)
  • phpenv(v0.9.0-rc.1)
  • PHP(8.1.0)
  • AWS CLI(2.9.1)
  • SAM CLI(1.65.0)
  • bref(v1.7)

環境構築

空のディレクトリ上でComposerを使ってbrefをインストールします。

$ composer require bref/bref

プロジェクトの初期化を行います。

$ vendor/bin/bref init

以下のメッセージが出力されます。brefでは、Webアプリケーション用またはイベントドリブン関数用のLambdaのどちらかを構築するか選択できるので、今回は1を選択します。

What kind of lambda do you want to create? (you will be able to add more functions later by editing `serverless.yml`) [Web application]:
  [0] Web application
  [1] Event-driven function

ディレクトリ配下に以下のファイルが生成されました。

├── sserverless.yml
├── vendor
│   └── async-aws
│    └── ...
├── composer.json
├── composer.lock
└── index.php
  • デフォルトでserverless.ymlが生成されます。これはサーバレスのIacツールであるServerless Framework(以下、sls)で必要となるテンプレートファイルです。今回はIacツールにAWS SAM(以下、SAM)を使用するので、serverless.ymlを削除しSAM用のtemplete.yamlを作成します

  • template.yamlのLayersパラメータに、bref公式ドキュメントに紹介されているLambda Layerの最新ARNを指定します。今回はarn:aws:lambda:ap-northeast-1:209497400698:layer:php-81:34を指定します。注意してほしいのが、Webアプリケーション用とイベントドリブン用で対象のARNが異なっており、Webアプリケーション用を選択した場合はphp-81-fpm:34用のARNを選択する必要があります

  • Runtimeにprovided.al2を指定しておりますが、これはAWS が提供するパブリックの ECR に配備されている provided:al2 のイメージをベースイメージとして指定しています

  • template.yaml

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Sample SAM Template for handson-bref

Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
        FunctionName: hello-world-function
        CodeUri: .
        Runtime: provided.al2
        Handler: index.php
        MemorySize: 1024
        Timeout: 30
        Layers:
            - arn:aws:lambda:ap-northeast-1:209497400698:layer:php-81:34
  • index.php
<?php declare(strict_types=1);

require __DIR__ . '/vendor/autoload.php';

return function ($event) {
    return 'Hello ' . ($event['name'] ?? 'world');
};

デプロイ

BASEではサーバレスのIac管理をSAMで行うことが多いので、SAMを使用したデプロイを実施します。

  • 本来ならsam buildを使用してビルドを行いたいのですが、カスタムランタイムを設定している場合はmakefileを自身で用意する必要があり手間がかかってしまうので、Lambdaパッケージ用のS3バケットを用意します
$ aws s3 mb s3://furukawa-bref-test --profile {任意}

SAM CLIを使用してパッケージングを行います。

$ sam package \ 
--template-file template.yaml \
--output-template-file bref-output.yaml \
--s3-bucket furukawa-bref-test \
--profile {任意}

SAM CLIを使用してデプロイを行います。

$ sam deploy --template-file bref-output.yaml \                                                                                                                               
--stack-name furukawa-bref-test
--profile {任意}
--capabilities CAPABILITY_IAM

デプロイが完了したので、Lambdaコンソール上で試しにテストを行います。

問題なくLambda関数を実行できました。

おわりに

brefを使用することで、DockerfileとBootstrapを使用せずに、LambdaランタイムをPHPに設定することができました。ただし、brefを使用する際に以下の点に注意が必要です。

  • brefで用意されているLambda Layerを使用すると、sam buildを使用したデプロイができない
  • bref(v1.7)ではarm64に対応していない
    • GitHub Issueによると、β版のbref(v2.0)ではarm64に対応するようなので、もうしばらく時間が必要
  • Lambda LayerのARNに、${bref:layer.php-81}を指定することでPHP8.1の最新のマイナーバージョンを取得してくれるが、 slsのみの対応

次回は、brefを使用してSlackbotを作ってみたいと思います。

明日は、kondo.hirotakaさん、yusakuさんの記事です。お楽しみに!!