Local development

To run your applications locally with an architecture close to production you can use the sam command line tool from AWS.

PHP functions

The serverless invoke local command invokes your PHP functions locally. It is necessary to use the --docker option so that Bref layers are correctly downloaded. You can provide an event if your function expects one.

For example, given this function:

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

functions:
    myFunction:
        handler: index.php
        layers:
            - ${bref:layer.php-73}

You can invoke it with or without event data:

$ serverless invoke local --docker -f myFunction
Hello world

$ serverless invoke local --docker -f myFunction --data '{"name": "Jane"}'
Hello Jane

Learn more in the serverless invoke local documentation or run serverless invoke local --help.

HTTP applications

If you want to keep things simple, you can run your PHP application like you did without Bref. For example with your favorite framework:

If you are not using any framework, you can use PHP's built-in server:

php -S localhost:8000 index.php
# The application is now available at http://localhost:8000/

In order to run the application locally in an environment closer to production, you can use the Bref Docker images. For example for an HTTP application, create the following docker-compose.yml:

version: "3.5"

services:
    web:
        image: bref/fpm-dev-gateway
        ports:
            - '8000:80'
        volumes:
            - .:/var/task
        depends_on:
            - php
        environment:
            HANDLER: index.php
    php:
        image: bref/php-73-fpm-dev
        volumes:
            - .:/var/task:ro

After running docker-compose up, the application will be available at http://localhost:8000/.

The HANDLER environment variable lets you define which PHP file will be handling all HTTP requests. This should be the same handler that you have defined in serverless.yml for your HTTP function.

Currently the Docker image support only one PHP handler. If you have multiple HTTP functions in serverless.yml, you can duplicate the service in docker-compose.yml to have one container per lambda function.

Read-only filesystem

The code will be mounted as read-only in /var/task, just like in Lambda. However when developing locally, it is common to regenerate cache files on the fly (for example Symfony or Laravel cache). You have 2 options:

  • mount the whole codebase as writable:

        volumes:
            - .:/var/task
  • mount a specific cache directory as writable (better):

        volumes:
            - .:/var/task:ro
            - ./cache:/var/task/cache

Assets

If you want to serve assets locally, you can define a DOCUMENT_ROOT environment variable:

version: "3.5"

services:
    web:
        image: bref/fpm-dev-gateway
        ports:
            - '8000:80'
        volumes:
            - .:/var/task
        links:
            - php
        environment:
            HANDLER: public/index.php
            DOCUMENT_ROOT: public
    php:
        image: bref/php-73-fpm-dev
        volumes:
            - .:/var/task:ro

In the example above, a public/assets/style.css file will be accessible at http://localhost:8000/assets/style.css.

Be aware that serving assets in production will not work like this out of the box. You will need to use a S3 bucket.

Xdebug

The docker container bref/php-<version>-fpm-dev comes with xdebug pre-installed. In order to enable it you can create a folder php/conf.dev.d in your project and include an ini file enabling xdebug:

zend_extension=xdebug.so

Now start the debug session by issueing a request to your application in the browser.

OSX

As Docker on Mac uses a virtual machine for running docker it can be tricky to listen to the xdebug port. By creating an alias for the loopback interface on the host with

sudo ifconfig lo0 alias 10.254.254.254

you can use this configuration start listening to xdebug connections in your preferred IDE:

[xdebug]
xdebug.remote_enable = 1
xdebug.remote_autostart = 0
xdebug.remote_host = '10.254.254.254'

Blackfire

The development FPM container comes with the blackfire extension. When using docker compose you can add following service configuration for the blackfire agent:

services:
  blackfire:
    image: blackfire/blackfire
    environment:
      BLACKFIRE_SERVER_ID: server-id
      BLACKFIRE_SERVER_TOKEN: server-token

In order to enable the probe you can create a folder php/conf.dev.d in your project and include an ini file enabling blackfire:

extension=blackfire
blackfire.agent_socket=tcp://blackfire:8707

For more details about using blackfire in a docker environment see the blackfire docs

Console applications

Console applications can be tested just like before: by running the command in your terminal.

For example with Symfony you can run bin/console <your-command> , or with Laravel run php artisan <your-command>.

If you want to run your console in an environment close to production, you can use the Bref Docker images. Here is an example of a docker-compose.yml file:

version: "3.5"

services:
    console:
        image: bref/php-73
        volumes:
            - .:/var/task:ro
        entrypoint: php

Then commands can be run via:

docker-compose run console php bin/console <your-command>