$30 off During Our Annual Pro Sale. View Details »

Running your PHP site on AWS Lambda

nealio82
February 21, 2019

Running your PHP site on AWS Lambda

Want to have immediate & easy website scaling, but also get rid of costly servers as they’re sitting idle 80% of the time waiting for visitors? Heard something about PHP and layers on AWS Lambda but have no idea what it means? You're not the only one! In this session we’ll get ourselves up-and-running with a PHP website on Lambda.

PHPUK Conference 2019

nealio82

February 21, 2019
Tweet

More Decks by nealio82

Other Decks in Programming

Transcript

  1. RUNNING YOUR
    PHP PROJECT
    ON AWS LAMBDA

    View Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. WE ARE HIRING!

    View Slide

  6. View Slide

  7. RUNNING YOUR
    PHP PROJECT
    ON AWS LAMBDA

    View Slide

  8. (coupling yourself to AWS for fun & profit)
    COUPLING
    YOURSELF
    TO AWS

    View Slide

  9. View Slide

  10. View Slide

  11. WHY?

    View Slide

  12. View Slide

  13. EC2

    View Slide

  14. EC2 Data Store

    View Slide

  15. EC2 Data Store

    View Slide

  16. EC2 Data Store
    Load Balancer

    View Slide

  17. WTF?

    View Slide

  18. EC2 Data Store
    Load Balancer

    View Slide

  19. EC2 Data Store
    Load Balancer
    EC2
    EC2

    View Slide

  20. EC2 Data Store
    Load Balancer
    EC2
    EC2

    View Slide

  21. EC2 Data Store
    Load Balancer
    EC2
    EC2

    View Slide

  22. SAY
    HELLO
    TO
    FaaS

    View Slide

  23. Think of FaaS as a server
    that doesn’t exist…

    View Slide

  24. …until you need it…

    View Slide

  25. …and goes away again
    once the job is done

    View Slide

  26. View Slide

  27. Container

    View Slide

  28. Container
    Bootstrap Code

    View Slide

  29. Container
    Bootstrap Code

    View Slide

  30. Container
    Bootstrap Code
    Application Code

    View Slide

  31. Container
    Bootstrap Code
    Application Code

    View Slide

  32. Container
    Bootstrap Code
    Application Code

    View Slide

  33. WAS A
    PITA
    RUNNING
    PHP ON
    LAMBDA

    View Slide

  34. View Slide

  35. Lambda function

    View Slide

  36. Lambda function
    JS Handler

    View Slide

  37. Lambda function
    JS Handler
    PHP Binary

    View Slide

  38. Lambda function
    JS Handler
    PHP Binary

    View Slide

  39. Lambda function
    JS Handler
    PHP Binary

    View Slide

  40. LAYERS

    View Slide

  41. View Slide

  42. View Slide

  43. • You can use up to 5 different layers in a Lambda function

    • The total unzipped size of code & layers must be < 250 MB

    • 1,000 concurrent invocations per region

    View Slide

  44. Lambda function
    JS Handler
    PHP Binary

    View Slide

  45. Lambda function
    Bootstrap
    PHP Layer
    Handler

    View Slide

  46. Lambda function
    Handler
    PHP Layer
    Bootstrap

    View Slide

  47. Lambda function
    Handler
    PHP Layer
    Bootstrap

    View Slide

  48. Lambda function
    Handler
    PHP Layer
    Bootstrap

    View Slide

  49. Lambda function
    Handler
    PHP Layer
    Bootstrap

    View Slide

  50. IS STILL
    A PITA
    RUNNING
    PHP ON
    LAMBDA

    View Slide

  51. https://bref.sh

    View Slide

  52. BREF AIMS TO MAKE
    RUNNING PHP APPS
    SIMPLE

    View Slide

  53. SIMPLIFY
    PROBLEMS
    BY REMOVING
    CHOICES

    View Slide

  54. PROVIDE SIMPLE
    AND FAMILIAR
    SOLUTIONS

    View Slide

  55. EMPOWER BY SHARING
    KNOWLEDGE

    View Slide

  56. WHAT
    DOES
    BREF ACTUALLY
    DO?

    View Slide

  57. View Slide

  58. View Slide

  59. View Slide

  60. SAM DEALS
    WITH
    DEPLOYING

    View Slide

  61. Lambda function
    Handler
    PHP Layer
    Bootstrap

    View Slide

  62. Lambda function
    Handler
    PHP Layer
    Bootstrap

    View Slide

  63. API Gateway
    Lambda function
    Handler
    PHP Layer
    Bootstrap

    View Slide

  64. API Gateway
    Lambda function
    Handler
    PHP Layer
    Bootstrap

    View Slide

  65. View Slide

  66. View Slide

  67. echo 'Hello, World!';
    phpinfo();
    hello-world.php

    View Slide

  68. $ composer require mnapoli/bref

    View Slide

  69. echo 'Hello, World!';
    phpinfo();
    hello-world.php

    View Slide

  70. $ php vendor/bin/bref init

    View Slide

  71. What kind of lambda do you want to create?
    [0] PHP function
    [1] HTTP application
    [2] Console application
    >

    View Slide

  72. What kind of lambda do you want to create?
    [0] PHP function
    [1] HTTP application
    [2] Console application
    > 1

    View Slide

  73. echo 'Hello, World!';
    phpinfo();
    hello-world.php
    index.php
    template.yaml

    View Slide

  74. AWSTemplateFormatVersion: '2010-09-09'
    Transform: AWS::Serverless-2016-10-31
    Description: ''
    Resources:
    MyFunction:
    Type: AWS::Serverless::Function
    Properties:
    FunctionName: 'my-function'
    Description: ''
    CodeUri: .
    Handler: index.php
    Timeout: 30 # in seconds (API Gateway has a timeout of 30 se
    Runtime: provided
    Layers:
    - 'arn:aws:lambda:us-east-1:209497400698:layer:php-73-fp
    Events:
    # The function will match all HTTP URLs
    HttpRoot:
    Type: Api
    Properties:
    Path: /
    Method: ANY
    HttpSubPaths:
    Type: Api
    Properties:
    Path: /{proxy+}
    hello-world.php
    template.yaml

    View Slide

  75. # ...
    Resources:
    MyFunction:
    Type: AWS::Serverless::Function
    Properties:
    FunctionName: 'my-function'
    Description: ''
    CodeUri: .
    Handler: index.php
    Timeout: 30 # in seconds
    Runtime: provided
    hello-world.php
    template.yaml

    View Slide

  76. # ...
    Resources:
    MyFunction:
    Type: AWS::Serverless::Function
    Properties:
    FunctionName: 'bref-hello-world'
    Description: ''
    CodeUri: .
    Handler: hello-world.php
    Timeout: 30 # in seconds
    Runtime: provided
    hello-world.php
    template.yaml

    View Slide

  77. # ...
    Layers:
    - 'arn:aws:lambda:us-east-1:209497400698:layer:php-73-fpm:1'
    Events:
    # The function will match all HTTP URLs
    HttpRoot:
    Type: Api
    Properties:
    Path: /
    Method: ANY
    HttpSubPaths:
    Type: Api
    Properties:
    Path: /{proxy+}
    Method: ANY
    # ...
    hello-world.php
    template.yaml

    View Slide

  78. # ...
    Layers:
    - 'arn:aws:lambda:eu-west-1:209497400698:layer:php-73-fpm:1'
    Events:
    # The function will match all HTTP URLs
    HttpRoot:
    Type: Api
    Properties:
    Path: /
    Method: ANY
    HttpSubPaths:
    Type: Api
    Properties:
    Path: /{proxy+}
    Method: ANY
    # ...
    hello-world.php
    template.yaml

    View Slide

  79. # ...
    Layers:
    - 'arn:aws:lambda:eu-west-1:209497400698:layer:php-73-fpm:1'
    Events:
    # The function will match all HTTP URLs
    HttpRoot:
    Type: Api
    Properties:
    Path: /
    Method: ANY
    HttpSubPaths:
    Type: Api
    Properties:
    Path: /{proxy+}
    Method: ANY
    # ...
    hello-world.php
    template.yaml

    View Slide

  80. # ...
    Layers:
    - 'arn:aws:lambda:eu-west-1:209497400698:layer:php-73-fpm:1'
    Events:
    # The function will match all HTTP URLs
    HttpRoot:
    Type: Api
    Properties:
    Path: /
    Method: ANY
    HttpSubPaths:
    Type: Api
    Properties:
    Path: /{proxy+}
    Method: ANY
    # ...
    hello-world.php
    template.yaml

    View Slide

  81. TESTING

    LOCALLY

    View Slide

  82. $ brew upgrade && brew update
    $ brew tap aws/tap
    $ brew install aws-sam-cli

    View Slide

  83. $ sam local start-api

    View Slide

  84. Error: Running AWS SAM projects locally
    requires Docker. Have you got it installed?

    View Slide

  85. $ sam local start-api

    View Slide

  86. * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)

    View Slide

  87. View Slide

  88. Invalid Layer name:
    arn:aws:lambda:eu-west-1:209497400698:layer:php-73-fpm

    View Slide

  89. $ sam local start-api --region=eu-west-1

    View Slide

  90. Downloading arn:aws:lambda:eu-
    west-1:209497400698:layer:php-73-fpm
    [####################################]
    32842625/32842625
    Building image...

    View Slide

  91. View Slide

  92. DEPLOYING

    View Slide

  93. $ aws s3 mb s3://bref-hello-world

    View Slide

  94. make_bucket: bref-hello-world

    View Slide

  95. $ sam package \
    --output-template-file .stack.yaml \
    --s3-bucket

    View Slide

  96. $ sam package \
    --output-template-file .stack.yaml \
    --s3-bucket bref-hello-world

    View Slide

  97. Uploading to cf39403efc50314711b61effd4f5c948
    2841371 / 2841371.0 (100.00%)
    Successfully packaged artifacts and wrote output
    template to file .stack.yaml.

    View Slide

  98. View Slide

  99. Execute the following command to deploy the
    packaged template
    aws cloudformation deploy --template-file /
    Users/neal/www/hello-world/.stack.yaml --stack-
    name

    View Slide

  100. $ aws cloudformation deploy --template-file /
    Users/neal/www/hello-world/.stack.yaml --stack-
    name

    View Slide

  101. $ aws cloudformation deploy --template-file /
    Users/neal/www/hello-world/.stack.yaml --stack-
    name bref-hello-world

    View Slide

  102. Waiter encountered a terminal failure state
    Status: FAILED. Reason: Requires capabilities :
    [CAPABILITY_IAM]

    View Slide

  103. $ sam deploy \
    --template-file .stack.yaml \
    --capabilities CAPABILITY_IAM \
    --stack-name

    View Slide

  104. $ sam deploy \
    --template-file .stack.yaml \
    --capabilities CAPABILITY_IAM \
    --stack-name bref-hello-world

    View Slide

  105. Failed to create/update the stack. Run the
    following command to fetch the list of events
    leading up to the failure
    aws cloudformation describe-stack-events --
    stack-name bref-hello-world

    View Slide

  106. View Slide

  107. Error occurred while GetObject. S3 Error Code:
    PermanentRedirect. S3 Error Message: The bucket
    is in this region: eu-west-2.

    View Slide

  108. View Slide

  109. $ aws s3 mb s3://bref-hello-world --region eu-west-1

    View Slide

  110. $ sam package \
    --output-template-file .stack.yaml \
    --s3-bucket bref-hello-world

    View Slide

  111. $ sam deploy \
    --template-file .stack.yaml \
    --capabilities CAPABILITY_IAM \
    --stack-name bref-hello-world

    View Slide

  112. Successfully created/updated stack - bref-hello-world

    View Slide

  113. View Slide

  114. View Slide

  115. API Gateway
    Lambda function
    Handler
    PHP Layer
    Bootstrap

    View Slide

  116. View Slide

  117. View Slide

  118. View Slide

  119. View Slide

  120. View Slide

  121. CLOUDWATCH
    HAS YOUR LOGS

    View Slide

  122. View Slide

  123. View Slide

  124. BRINGING
    YOUR OWN
    DOMAIN
    NAME

    View Slide

  125. https://o6zwsmm0uk.execute-api.eu-west-1.amazonaws.com/Prod/

    View Slide

  126. https://o6zwsmm0uk.execute-api.eu-west-1.amazonaws.com/Prod/

    View Slide

  127. View Slide

  128. View Slide

  129. View Slide

  130. View Slide

  131. View Slide

  132. View Slide

  133. View Slide

  134. View Slide

  135. View Slide

  136. RECAP

    View Slide

  137. • Looked at how FaaS could simplify our architecture & save us money

    • Installed AWS CLI

    • Added Bref to a project

    • Explored the template.yaml file

    • Used SAM Local to test

    • Created a deployment bucket

    • Packaged and deployed our application

    • Explored the stack

    • Tested the application on Lambda

    • Seen the logs in Cloudwatch

    • Added a custom domain name

    View Slide

  138. REFACTORING
    A FULLY
    FEATURED
    WEBSITE

    View Slide

  139. View Slide

  140. View Slide

  141. View Slide

  142. View Slide

  143. View Slide

  144. REMEMBER

    View Slide

  145. • Only /tmp is writeable

    • The total unzipped size of code & layers must be < 250 MB

    View Slide

  146. $ composer require mnapoli/bref

    View Slide

  147. $ php vendor/bin/bref init

    View Slide

  148. What kind of lambda do you want to create?
    [0] PHP function
    [1] HTTP application
    [2] Console application
    > 1

    View Slide

  149. # ...
    Resources:
    MyFunction:
    Type: AWS::Serverless::Function
    Properties:
    FunctionName: 'bref-kittyquotes'
    Description: ''
    CodeUri: .
    Handler: public/index.php
    Timeout: 30 # in seconds
    Runtime: provided
    MemorySize: 1024
    template.yaml
    bin
    public
    src
    templates
    config

    View Slide

  150. # ...
    Resources:
    WebApplication:
    Type: AWS::Serverless::Function
    Properties:
    FunctionName: 'bref-kittyquotes'
    Description: ''
    CodeUri: .
    Handler: public/index.php
    Timeout: 30 # in seconds
    Runtime: provided
    template.yaml
    bin
    public
    src
    templates
    config

    View Slide

  151. $ sam local start-api

    View Slide

  152. View Slide

  153. bin
    public
    src
    templates
    config
    template.yaml
    namespace App;
    class Kernel extends BaseKernel
    {
    // ...
    public function getCacheDir()
    {
    // When on the lambda only /tmp is writeable
    if (getenv('LAMBDA_TASK_ROOT') !== false) {
    return '/tmp/cache/' . $this->environment;
    }
    return $this->getProjectDir().'/var/cache'
    . $this->environment;
    }
    Kernel.php

    View Slide

  154. bin
    public
    src
    templates
    config
    template.yaml
    namespace App;
    class Kernel extends BaseKernel
    {
    // ...
    public function getLogDir()
    {
    // When on the lambda only /tmp is writeable
    if (getenv('LAMBDA_TASK_ROOT') !== false) {
    return '/tmp/log/';
    }
    return $this->getProjectDir().'/var/log';
    }
    Kernel.php

    View Slide

  155. PDOException > PDOException > DriverException
    An exception occurred in driver: could not find driver

    View Slide

  156. View Slide

  157. View Slide

  158. bin
    public
    php
    templates
    config
    template.yaml
    extension=pdo_mysql
    src
    conf.d
    php.ini

    View Slide

  159. CONNECTING THE DATABASE

    View Slide

  160. API Gateway
    Lambda function
    Handler
    PHP Layer
    Bootstrap

    View Slide

  161. API Gateway
    Lambda function
    Handler
    PHP Layer
    Bootstrap

    View Slide

  162. API Gateway
    Lambda function
    Handler
    PHP Layer
    Bootstrap
    API Gateway
    Data Store

    View Slide

  163. API Gateway
    VPC
    Lambda function
    Handler
    PHP Layer
    Bootstrap
    API Gateway
    Data Store

    View Slide

  164. # ...
    Resources:
    WebApplication:
    Type: AWS::Serverless::Function
    Properties:
    Environment:
    Variables:
    APP_ENV: prod
    DATABASE_URL: ‘mysql://db_user:db_pass@...’
    # ...
    template.yaml
    bin
    public
    src
    templates
    config

    View Slide

  165. View Slide

  166. View Slide

  167. View Slide

  168. $ aws s3 mb s3://bref-kitty-quotes-bucket

    View Slide

  169. $ sam package \
    --output-template-file .stack.yaml \
    --s3-bucket bref-kitty-quotes-bucket

    View Slide

  170. $ sam deploy \
    --template-file .stack.yaml \
    --capabilities CAPABILITY_IAM \
    --stack-name bref-kitty-quotes-app

    View Slide

  171. Failed to create/update the stack. Run the following
    command to fetch the list of events leading up to the
    failure
    aws cloudformation describe-stack-events --stack-name
    bref-kitty-quotes-app

    View Slide

  172. Unzipped size must be smaller than 155850286 bytes

    View Slide

  173. $ composer install --optimize-autoloader --no-dev
    $ rm -rf node_modules

    View Slide

  174. $ composer install --optimize-autoloader --no-dev
    $ rm -rf node_modules
    $ rm -rf var/cache
    $ rm -rf .idea/*
    $ rm -rf .git/*

    View Slide

  175. cp -Rf ../bref-kitty-quotes-symfony/* . \
    && rm -rf var/cache/* \
    && rm -rf node_modules \
    && composer install --optimize-autoloader --no-dev \
    && php bin/console cache:warmup --env=prod \
    && sam package --output-template-file .stack.yaml
    --s3-bucket bref-kitty-quotes-bucket \
    && sam deploy --template-file .stack.yaml
    --stack-name bref-kitty-quotes-app
    --capabilities CAPABILITY_IAM

    View Slide

  176. Successfully created/updated stack - bref-kitty-quotes-app

    View Slide

  177. View Slide

  178. View Slide

  179. // ...
    if (Encore.isProduction()) {
    Encore.setPublicPath(
    'https://s3-eu-west-1.amazonaws.com/'
    + ‘kittyquotes-site-assets’
    );
    Encore.setManifestKeyPrefix('build/');
    }
    webpack.config.js
    template.yaml
    bin
    public
    src
    templates
    config
    php

    View Slide

  180. $ yarn encore production

    View Slide

  181. View Slide

  182. View Slide

  183. View Slide

  184. bin
    config
    framework:
    assets:
    base_urls:
    -
    'https://s3-eu-west-1.amazonaws.com/%env(ASSETS_BUCKET_NAME)%'
    packages
    assets.yaml
    webpack.config.js
    template.yaml
    public
    src
    templates
    php

    View Slide

  185. View Slide

  186. View Slide

  187. API Gateway
    Data Store
    Lambda function
    Handler
    PHP Layer
    Bootstrap

    View Slide

  188. Lambda function
    Handler
    PHP Layer
    Bootstrap
    API Gateway
    Data Store
    Sessions

    View Slide

  189. API Gateway
    Data Store
    Lambda function
    Handler
    PHP Layer
    Bootstrap
    Sessions

    View Slide

  190. API Gateway
    Data Store
    Lambda function
    Handler
    PHP Layer
    Bootstrap
    Sessions
    Handler
    PHP Layer
    Bootstrap
    Sessions

    View Slide

  191. API Gateway
    Data Store
    Sessions
    Sessions
    Lambda function
    Handler
    PHP Layer
    Bootstrap
    Handler
    PHP Layer
    Bootstrap

    View Slide

  192. View Slide

  193. bin
    config
    services:
    # ...
    Symfony\Component\HttpFoundation\Session
    \Storage\Handler\PdoSessionHandler:
    arguments:
    - !service { class: PDO, factory: >
    'database_connection:getWrappedConnection' }
    - { lock_mode: 1 }
    services.yaml
    webpack.config.js
    template.yaml
    public
    src
    templates
    php

    View Slide

  194. bin
    config
    framework:
    # ...
    session:
    # ...
    handler_id: >
    Symfony\Component\HttpFoundation\Session
    \Storage\Handler\PdoSessionHandler
    packages
    framework.yaml
    webpack.config.js
    template.yaml
    public
    src
    templates
    php

    View Slide

  195. View Slide

  196. bin
    public
    src
    templates
    config
    final class Version20180828140534 extends AbstractMigration
    {
    public function up(Schema $schema): void
    {
    $this->addSql("CREATE TABLE `sessions` (
    `sess_id` VARCHAR(128) NOT NULL PRIMARY KEY,
    `sess_data` BLOB NOT NULL,
    `sess_time` INTEGER UNSIGNED NOT NULL,
    `sess_lifetime` MEDIUMINT NOT NULL
    ) COLLATE utf8_bin, ENGINE = InnoDB;");
    }
    public function down(Schema $schema): void
    {
    $this->addSql('DROP TABLE sessions');
    }
    }
    Migrations
    Version2019____.php
    webpack.config.js
    template.yaml
    php

    View Slide

  197. CONSOLE COMMANDS

    View Slide

  198. Globals:
    Function:
    Environment:
    Variables:
    DATABASE_URL: ‘mysql://db_user:db_pass@...’
    Resources:
    WebApplication:
    # ...
    Console:
    Type: AWS::Serverless::Function
    Properties:
    FunctionName: 'bref-kittyquotes-console'
    CodeUri: .
    Handler: bin/console # or `artisan` for Laravel
    Runtime: provided
    Layers:
    # PHP runtime
    - 'arn:aws:lambda:eu-west-1:209497400698:layer:php-73:1'
    # Console layer
    - 'arn:aws:lambda:eu-west-1:209497400698:layer:console:1'
    webpack.config.js
    template.yaml
    bin
    public
    src
    templates
    config
    php

    View Slide

  199. Globals:
    Function:
    Environment:
    Variables:
    DATABASE_URL: ‘mysql://db_user:db_pass@...’
    Resources:
    WebApplication:
    # ...
    Console:
    Type: AWS::Serverless::Function
    Properties:
    FunctionName: 'bref-kittyquotes-console'
    CodeUri: .
    Handler: bin/console # or `artisan` for Laravel
    Runtime: provided
    Layers:
    # PHP runtime
    - 'arn:aws:lambda:eu-west-1:209497400698:layer:php-73:1'
    # Console layer
    - 'arn:aws:lambda:eu-west-1:209497400698:layer:console:1'
    webpack.config.js
    template.yaml
    bin
    public
    src
    templates
    config
    php

    View Slide

  200. Globals:
    Function:
    Environment:
    Variables:
    DATABASE_URL: ‘mysql://db_user:db_pass@...’
    Resources:
    WebApplication:
    # ...
    Console:
    Type: AWS::Serverless::Function
    Properties:
    FunctionName: 'bref-kittyquotes-console'
    CodeUri: .
    Handler: bin/console # or `artisan` for Laravel
    Runtime: provided
    Layers:
    # PHP runtime
    - 'arn:aws:lambda:eu-west-1:209497400698:layer:php-73:1'
    # Console layer
    - 'arn:aws:lambda:eu-west-1:209497400698:layer:console:1'
    webpack.config.js
    template.yaml
    bin
    public
    src
    templates
    config
    php

    View Slide

  201. $ php vendor/bin/bref cli bref-kittyquotes-console -- \
    doctrine:migrations:migrate --force

    View Slide

  202. $ php vendor/bin/bref cli bref-kittyquotes-console -- \
    doctrine:migrations:migrate --force

    View Slide

  203. $ php vendor/bin/bref cli bref-kittyquotes-console -- \
    doctrine:migrations:migrate --force

    View Slide

  204. ++ 1 migrations executed
    ++ 1 sql queries

    View Slide

  205. View Slide

  206. Handler
    PHP Layer
    Bootstrap
    Lambda function
    API Gateway
    Data Store

    View Slide

  207. Handler
    PHP Layer
    Bootstrap
    Lambda function
    API Gateway
    Data Store

    View Slide

  208. API Gateway
    Data Store
    File Store
    Handler
    PHP Layer
    Bootstrap
    Lambda function

    View Slide

  209. parameters:
    app.path.kitty_images: ‘%env(APP_UPLOADS_BUCKET_NAME)%’
    bin
    config
    services.yaml
    webpack.config.js
    template.yaml
    public
    src
    templates
    php

    View Slide

  210. # ...
    Resources:
    WebApplication:
    Type: AWS::Serverless::Function
    Properties:
    Environment:
    Variables:
    APP_UPLOADS_BUCKET_NAME: kittyquotes-uploads
    webpack.config.js
    template.yaml
    bin
    public
    src
    templates
    config
    php

    View Slide

  211. View Slide

  212. bin
    config
    twig:
    # ...
    globals:
    kitty_uploads_bucket: '%app.path.kitty_images%'
    packages
    twig.yaml
    webpack.config.js
    template.yaml
    public
    src
    templates
    php

    View Slide

  213. bin
    public
    src
    templates
    config

    src="{{ kitty_uploads_bucket }}/{{ quote.kitty.image }}"
    alt="{{ quote.kitty.name }}”
    >

    template.yaml
    webpack.config.js
    quote
    quote-card.html.twig
    php

    View Slide

  214. View Slide

  215. UPLOADING
    NEW IMAGES
    OF KITTIES

    View Slide

  216. pre-signed URLs

    View Slide

  217. Client Server Amazon S3

    View Slide

  218. Client Server Amazon S3
    Get Pre-Signed URL

    View Slide

  219. Client Server Amazon S3
    Get Pre-Signed URL
    Get Pre-Signed URL

    View Slide

  220. Client Server Amazon S3
    Get Pre-Signed URL
    Get Pre-Signed URL
    One-time use URL

    View Slide

  221. Client Server Amazon S3
    Get Pre-Signed URL
    Get Pre-Signed URL
    One-time use URL
    One-time use URL

    View Slide

  222. Client Server Amazon S3
    Get Pre-Signed URL
    Get Pre-Signed URL
    One-time use URL
    One-time use URL
    PUT file to One-time use URL
    200 OK

    View Slide

  223. Client Server Amazon S3
    Get Pre-Signed URL
    Get Pre-Signed URL
    One-time use URL
    One-time use URL
    PUT file to One-time use URL
    200 OK
    Update record

    View Slide

  224. Client Server Amazon S3
    Get Pre-Signed URL
    Get Pre-Signed URL
    One-time use URL
    One-time use URL
    PUT file to One-time use URL
    200 OK
    Update record
    Delete previous file

    View Slide

  225. bin
    public
    src
    config
    namespace App\Controller;
    class AdminController extends BaseAdminController
    {
    /**
    * @Route("/kitty/upload-image", name="upload_kitty_image")
    */
    public function uploadKittyImageAction()
    {
    //...
    }
    /**
    * @Route("/kitty/upload-image-pre-signed-url/{filename}",
    name="upload_kitty_image_pre_signed_url", methods={"GET"})
    */
    public function getPresignedUrlAction($filename)
    {
    //...
    }
    }
    php
    Controller
    AdminController.php
    templates
    template.yaml
    webpack.config.js

    View Slide

  226. bin
    public
    src
    templates
    config
    getPreSignedUrl = function (files) {
    file = files[0];
    $.ajax({
    url: '/admin/kitty/upload-image-pre-signed-url/' + file.name,
    type: "GET",
    dataType: "json",
    cache: false
    })
    .done(function (data) {
    preSignedUrl = data.url;
    document.getElementById('kitty_image_image').value =
    data.filename;
    });
    }
    function uploadFile() {
    $.ajax({
    url: preSignedUrl,
    type: "PUT",
    data: file,
    contentType: file.type,
    processData: false
    }).done(function () {
    $("form[name='kitty_image']").submit();
    });
    }
    uploader.html.twig
    template.yaml
    webpack.config.js
    php

    View Slide

  227. View Slide

  228. $ composer remove vich/uploader-bundle

    View Slide

  229. bin
    public
    src
    config
    Entity
    Kitty.php
    namespace App\Entity;
    class Kitty
    {
    // ...
    /**
    * @Vich\UploadableField(
    * mapping="product_image",
    * fileNameProperty="imageName",
    * size=“imageSize"
    * )
    *
    * @var File
    */
    private $imageFile;
    /**
    * @ORM\Column(type="datetime")
    *
    * @var \DateTime
    */
    private $updatedAt;
    templates
    template.yaml
    webpack.config.js
    php

    View Slide

  230. namespace App\Entity;
    class Kitty
    {
    // ...
    /**
    * @param File|\
    * Symfony\Component\HttpFoundation\File\UploadedFile $image
    */
    public function setImageFile(?File $image = null): void
    {
    $this->imageFile = $image;
    if (null !== $image) {
    $this->updatedAt = new \DateTimeImmutable();
    }
    }
    public function getImageFile(): ?File
    {
    return $this->imageFile;
    }
    }
    bin
    public
    src
    config
    Entity
    Kitty.php
    templates
    template.yaml
    webpack.config.js
    php

    View Slide

  231. View Slide

  232. View Slide

  233. View Slide

  234. RECAP

    View Slide

  235. • Added Bref to an existing site

    • Fixed assets by moving them to a CDN

    • Moved session storage to the database

    • Ran console commands by adding another layer

    • Used pre-signed URLs for image uploading

    View Slide

  236. View Slide

  237. PERFORMANCE

    View Slide

  238. View Slide

  239. VPC
    Lambda function
    Handler
    PHP Layer
    Bootstrap
    API Gateway
    Data Store

    View Slide

  240. source: https://medium.freecodecamp.org/lambda-vpc-cold-starts-a-latency-killer-5408323278dd

    View Slide

  241. source: https://medium.freecodecamp.org/lambda-vpc-cold-starts-a-latency-killer-5408323278dd

    View Slide

  242. source: https://medium.freecodecamp.org/lambda-vpc-cold-starts-a-latency-killer-5408323278dd

    View Slide

  243. View Slide

  244. View Slide

  245. source: https://github.com/mnapoli/bref-benchmark
    JS vs PHP

    View Slide

  246. source: https://github.com/mnapoli/bref-benchmark
    JS vs PHP

    View Slide

  247. GOING FURTHER

    View Slide

  248. MICRO
    SERVICES

    View Slide

  249. What kind of lambda do you want to create?
    [0] PHP function
    [1] HTTP application
    [2] Console application
    >

    View Slide

  250. What kind of lambda do you want to create?
    [0] PHP function
    [1] HTTP application
    [2] Console application
    > 0

    View Slide

  251. ROLLING
    YOUR
    OWN

    View Slide

  252. https://github.com/
    stechstudio/bref-extensions

    View Slide

  253. https://github.com/
    mnapoli/bref

    View Slide

  254. runtime
    ./configure \
    --build=x86_64-pc-linux-gnu \
    --prefix=${INSTALL_DIR} \
    --enable-option-checking=fatal \
    --enable-maintainer-zts \
    --with-config-file-path=${INSTALL_DIR}/etc/php \
    --with-config-file-scan-dir=${INSTALL_DIR}/etc/php/conf.d:/var/tas
    --enable-fpm \
    --disable-cgi \
    --enable-cli \
    --disable-phpdbg \
    --disable-phpdbg-webhelper \
    --with-sodium \
    --with-readline \
    --with-openssl \
    --with-zlib=${INSTALL_DIR} \
    --with-zlib-dir=${INSTALL_DIR} \
    --with-curl \
    --enable-exif \
    --enable-ftp \
    --with-gettext \
    --enable-mbstring \
    --with-pdo-mysql=shared,mysqlnd \
    --enable-pcntl \
    --enable-zip \
    --with-pdo-pgsql=shared,${INSTALL_DIR} \
    --enable-intl=shared \
    --enable-opcache-file
    php
    php.Dockerfile

    View Slide

  255. $ make publish

    View Slide

  256. View Slide

  257. View Slide

  258. View Slide

  259. View Slide

  260. • Documentation

    • Speed & stability

    • A recommended method of creating your own runtimes

    • Better framework integrations

    View Slide

  261. JOIN US

    View Slide

  262. View Slide

  263. https://bref.sh

    View Slide

  264. @nealio82
    https://bref.sh

    View Slide