We have three options. We can:
- Package our function as a container image.
- Embed a custom PHP runtime and bootstrap file.
- Use a Lambda Layer to contain the PHP runtime and/or bootstrap.
This article will focus on the first option; how to build, push and deploy a PHP container image to Lambda with Docker and the AWS SAM CLI.
This article will explain:
- How to structure the function.
- How to test locally.
- How to deploy.
- A bootstrap file fetches the next invocation from the Lambda runtime.
- The boostrap passes event data to PHP.
- PHP processes the event and returns a success or error response to the Lambda runtime.
Ensure you have installed:
Create your function with this structure:
MyApp
├── src
│ └── MyClass.php
├── 99-prod-overrides.ini
├── bootstrap
├── composer.json
├── Dockerfile
├── handler.php
├── template.yaml
Use composer to install dependencies, define autoload standards and dump the autoload file.
The bootstrap file fetches the next lambda invocation and hands it to handler.php
with the PHP CLI.
While we could write the bootstrap in PHP, using bash gives us 2 advantages:
- a smaller boostrap gives us a faster Lambda warm up.
- a bash bootstrap contains memory leaks to a single invocation.
The bootstrap
Add ini overrides in the 99-prod-overrides.ini file.
We build from the official AWS lambda provided Amazon Linux 2 image. You can extend from any base, but you will then need to implement the Lambda runtime yourself.
We use unofficial Remi repo in this example to simplify installing PHP and PHP dependencies and extensions. Use this AWS tutorial if you want to go the official route.
The dockerfile follows these steps:
- Install packages.
- Copy bootstrap to
/var/runtime
- Copy handler and code to
/var/task
- Install dependencies.
The handler.php file passes event data to your function code and returns a success or error response to the Lambda runtime.
In this examplehandler.php
passes event data to the MyClass::run
static function. It returns an error response if any exception is thrown.
We use the SAM CLI to build, develop and deploy serverless cuntionss. SAM uses CloudFormation Templates to define resources.
We use the Properties.PackateType
, and MetaData.Docker*
properties to tell SAM and AWS to
It sets the DEST
build arg to aws
- you can create a parameter, or a git ignored local template file to build the local dev version.
We can test the system in 2 ways:
sam build
sam local invoke PhpTestFunction
If it works you should see:
Invoking Container created from phptestfunction:latest
Building image..........
Skip pulling image and use local one: phptestfunction:rapid-1.13.2.
START RequestId: xxx-xxx-xxx-xxx Version: $LATEST
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 34 100 16 100 18 16000 18000 --:--:-- --:--:-- --:--:-- 34000
END RequestId: xxx-xxx-xxx-xxx
REPORT RequestId: xxx-xxx-xxx-xxx Init Duration: 0.50 ms Duration: 71.64 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 128 MB
Yep, it is working
In one terminal build and run with docker:
docker build --build-arg DEST=aws -t php-lambda .
docker run -p 9000:8080 -it php-lambda
In another terminal POST to the runtime
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d "{}"
If it works, in the docker run terminal you should see:
START RequestId: d9e7cfe1-eddc-48a8-9211-a1a3e44ec3bb Version: $LATEST
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 34 100 16 100 18 8000 9000 --:--:-- --:--:-- --:--:-- 17000
END RequestId: d9e7cfe1-eddc-48a8-9211-a1a3e44ec3bb
REPORT RequestId: d9e7cfe1-eddc-48a8-9211-a1a3e44ec3bb Init Duration: 0.34 ms Duration: 50.08 ms Billed Duration: 100 ms Memory Size: 3008 MB Max Memory Used: 3008 MB
In the cURL terminal you should see:
Yep, it is working