Using Symfony on Lambda

For those going down the server-less route and using Symfony, this will hopefully give you a decent starting point.

I’ve added a ‘part 2‘ to this post, with performance optimisations, as well as handling being behind the API Gateway.

This uses a project called Bref – their website is a great starting point and has loads of info.

Ingredients (what you’ll need on-hand);

Method (how do we do this);

A lot of these instructions come from https://bref.sh

For this example, we’ll use ap-southeast-2 as the region (as all my scripts are written using it)

IMPORTANT: If you decide to use a different region (eg. one closer to home/your users), make sure you use the same region for S3 as well as the runtime (mentioned later). Otherwise you’ll run into permission issues you’ll never be able to solve!

2) Jump into the project dir (eg. my-project), and install bref using composer;

1) Install the Symfony skeleton project (see https://symfony.com/doc/current/setup.html) & check to make sure it works as expected.

composer require mnapoli/bref

You may also need to run the following;

vendor/bin/bref init

3) Create an AWS S3 bucket to store your ‘packaged’ files;

aws s3 mb s3://symfony-lambda --region=ap-southeast-2

4) Create a deploy.sh executable file to save yourself some typing;

#!/bin/bash

# Package up your files and send it to an S3 bucket you're going to use;
sam package --output-template-file .stack-symfony.yaml     --s3-bucket symfony-lambda --region=ap-southeast-2

# Deploy (using cloud-formation, which will create your lambda function, etc)
sam deploy --template-file .stack-symfony.yaml --stack-name symfony-lambda --capabilities CAPABILITY_IAM --region=ap-southeast-2

5) Create a cloudformation template file (we’ll call this ‘.stack-symfony.yaml’ … if you want to call it something different, put in the new name in the above command instead);

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


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


Globals:
    Function:
        Environment:
            Variables:
                APP_ENV: prod
Resources:
  Website:
    Properties:
      CodeUri: s3://<your s3 bucket here>/94ce2f32ac156cd3f06208d3e05dca8f
      Description: ''
      Events:
        HttpRoot:
          Properties:
            Method: ANY
            Path: /
          Type: Api
        HttpSubPaths:
          Properties:
            Method: ANY
            Path: /{proxy+}
          Type: Api
      FunctionName: symfony-website
      Handler: public/index.php
      MemorySize: 1024
      Layers:
        - arn:aws:lambda:ap-southeast-2:416566615250:layer:php-72-fpm:8
      Runtime: provided
      Timeout: 30
    Type: AWS::Serverless::Function
  MyFunctionCli:
    Properties:
      CodeUri: s3://<your s3 bucket here>/94ce2f32ac156cd3f06208d3e05dca8f
      FunctionName: symfony-console
      Handler: bin/console
      Timeout: 120  # in seconds
      Layers:
        - arn:aws:lambda:ap-southeast-2:416566615250:layer:php-72-fpm:8
        - arn:aws:lambda:ap-southeast-2:416566615250:layer:console:4
      Runtime: provided
    Type: AWS::Serverless::Function

Runtimes (basically the PHP executable which is needed by Lambda (PHP isn’t built into lambda, so we supply it as a ‘layer’). See; https://bref.sh/docs/runtimes/

In the file above, add in your s3 bucket name, and replace the ‘layers’ mentioned above with the later from your region (if you’ve decided to use a different one). See; https://bref.sh/docs/runtimes/

6) Run your ./deploy.sh script and follow the prompts if there’s any issues.

I ran into multiple permission issues which were all easily solved by giving access to the user i’d created for this project.

See the Symfony bref guide for more details if you get stuck; https://bref.sh/docs/frameworks/symfony.html

Cost;

This article is of course free, but there’s some on-going costs you’ll need to consider with Lambda. The few websites i’ve read regarding this seem to indicate it’s cheaper than running an EC2 instance (both from an actual cost and a time-cost in maintaining the thing), but of course you can do a lot of things with EC2!

The cost estimates i’m using come from US East (Ohio), and were taken on 8/Feb/2019;

  • Lambda (for your actual PHP server-side code)
    • $3.50/million requests – first 333 million requests/month
    • AWS Lambda – Compute Free Tier – 400,000 GB-Seconds – US East (Ohio)12.163 Lambda-GB-Second
    • AWS Lambda – Requests Free Tier – 1,000,000 Requests – US East (Ohio)
  • S3 (for storage of your packaged site, as well as any assets – css/images/js/uploaded files);
    • $0.005 per 1,000 PUT, COPY, POST, or LIST requests
    • $0.004 per 10,000 GET and all other requests
    • $0.023 per GB – first 50 TB / month of storage used
  • Some others include;
    • Bandwidth
    • CloudFront (for serving up your assets if you use it later on)
    • Relational Database Service (for a database if you need one)
    • Route 53 (for your DNS needs)
    • Simple Email Service (for sending emails)

Inspiration from this comes from this YouTube vid – well worth watching;