You work with Symfony, but the concept of dependency injection is a little blurry for you? Find out how to take advantage of the component reading this article.
PHP & Serverless with Bref - part 2
This article is a follow-up to this first part which introduces serverless computing. In this second part, we will first see what the layers are in AWS Lambda and how to implement them. Then we will see how to use the Bref framework.
How it works
An AWS Lambda environment includes:
- the runtime of the chosen language (Java, Go, PowerShell, Node.js, C #, Python, Ruby by default)
- the implementation of Lambda runtime API, i.e. the lifecycle of the execution of the environment and the invocation of serverless functions
The lifecycle of a Lambda runtime consists of an initialization phase and several (as many as necessary) invocation phases.
The initialization phase represents the time between the moment when the environment starts the runtime and the moment when the code of a function is executed. This phase is performed only once during the life cycle of the environment.
After initialization, the execution environment goes into the invocation phase and will constantly check and execute tasks, until the environment shuts down.
Since November 2018, it is possible to declare your own runtimes for Lambda functions, but also to incorporate reusable components in the form of Layers.
You can implement a runtime in any language. A runtime is a program that executes the
handler of a Lambda function when it is called. A runtime can be included in the function deployment package in the form of an executable file named
bootstrap (we will see an example later in this article).
A Lambda function can be configured to download additional code and content as a layer. A layer is a ZIP archive that contains libraries, a custom runtime or other dependencies.
If you have already written serverless functions in Node.js, you know that you must package the entire
node_modules folder for every function (since they are deployed independently from each other). This slows down the deployment process and makes the builds slow.
But now, it is possible to publish the
node_modules folder as a shared and reusable layer for all our functions. This means that we could have a layer for our custom runtime, another layer which contains our dependencies and configure our functions to use these 2 layers. Note that a function has a limit of 5 layers.
Take the following simple function as an example:
I am going to create a
layers/php folder in my application and I will place my layer there.
To create a custom runtime, we need a
bootstrap file which will contain the logic of our runtime in charge of invoking our functions.
We also need a PHP executable capable of interpreting our code. I'm going to create a
bin folder in my layer folder to place my
php binary. To generate a binary, I recommend you read this article.
When deploying a layer, it is placed in the
/opt folder in the containers. So my
bootstrap file could look like this:
Here is an example of
runtime.php inspired by the article on the AWS blog.
We will use
Guzzle to make HTTP calls, therefore I will first execute the following command:
composer require guzzlehttp/guzzle
To summarize, we currently have the following file structure:
layers/ php/ bin/ php #binary file bootstrap runtime.php src/ profession.php vendor/ guzzlehttp/
I will use the serverless framework to deploy my layer and my function:
As we can see, in my
occupation function, the
handler contains the name of my file
profession.php and the
occupation method. This is how I configured it in
It is therefore up to us to configure the way we name the handlers and the way to call them in the runtime.
The name of our layer
PhpLambdaLayer corresponds to its CloudFormation reference. You can read the details here.
To deploy the function and the layer, execute the following command:
Finally, let's invoke the
So we just made a working example with a layer capable of executing PHP code.
Now imagine that you have a large application, say a REST API in Symfony, that you would like to deploy on AWS Lambda. It would be necessary to develop a much more advanced runtime capable of integrating with the front controller of Symfony, and why not with the console as well. We would also have to modify the PHP layer to add all the libraries we would need and to recompile the PHP binary.
Fortunately for us, an open source solution exists to manage all of this: Bref.
Bref is an open source Composer package that allows us to deploy PHP applications on AWS Lambda. It is developed by Matthieu Napoli.
- the documentation
- PHP runtimes for AWS Lambda
- deployment tools
- integration with PHP frameworks
I suggest we deploy a Symfony application on AWS Lambda using Bref.
To create my application:
Next, let's modify the default controller as follows (to use the same example as above):
Now let's add the Bref library:
Finally, let's configure the deployment with serverless framework:
The list of layers made available by Bref can be consulted here. I also recommend that you read the Bref documentation, it is very clear and provides plenty of examples that you may need.
We need to keep in mind that with most cloud providers the filesystem is read only. Hence, we need to change the
cache folders of our application:
Last step, deployment:
My application is available on the URL indicated in the endpoints. Here is the result:
That's it. We just deployed a Symfony application to AWS Lambda using Bref! As you can see, it is a pretty straight forward process...
You can now enjoy deploying PHP applications to a serverless infrastructure :)