Skip to content

Commit

Permalink
PHPLIB-1163 Create tutorial for using MongoDB with Bref (#1273) (#1282)
Browse files Browse the repository at this point in the history
  • Loading branch information
GromNaN authored Apr 19, 2024
1 parent 25182bc commit af89a5e
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ psalm.xml
.phpbench/
phpbench.json

# bref
.serverless/

mongocryptd.pid
19 changes: 19 additions & 0 deletions docs/examples/aws-lambda/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "mongodb/bref-tutorial",
"type": "project",
"license": "MIT",
"repositories": [
{
"type": "path",
"url": "../../..",
"options": {
"symlink": false
}
}
],
"require": {
"bref/bref": "^2.1",
"bref/extra-php-extensions": "^1.4",
"mongodb/mongodb": "@dev"
}
}
31 changes: 31 additions & 0 deletions docs/examples/aws-lambda/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

use MongoDB\Client;

require_once __DIR__ . '/vendor/autoload.php';

$uri = getenv('MONGODB_URI');

try {
$client = new Client($uri);
$planets = $client
->selectCollection('sample_guides', 'planets')
->find([], ['sort' => ['orderFromSun' => 1]]);
} catch (Throwable $exception) {
exit($exception->getMessage());
}

?>
<!DOCTYPE html>
<html lang="en">
<head>
<title>MongoDB Planets</title>
</head>
<body>
<ul>
<?php foreach ($planets as $planet) : ?>
<li><?= $planet->name ?></li>
<?php endforeach ?>
</ul>
</body>
</html>
22 changes: 22 additions & 0 deletions docs/examples/aws-lambda/serverless.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
service: app

provider:
name: aws
region: us-east-1
environment:
MONGODB_URI: ${env:MONGODB_URI}

plugins:
- ./vendor/bref/bref
- ./vendor/bref/extra-php-extensions

functions:
api:
handler: index.php
description: ''
runtime: php-83-fpm
timeout: 28 # in seconds (API Gateway has a timeout of 29 seconds)
events:
- httpApi: '*'
layers:
- ${bref-extra:mongodb-php-83}
1 change: 1 addition & 0 deletions docs/tutorial.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ Tutorials
/tutorial/indexes
/tutorial/tailable-cursor
/tutorial/example-data
/tutorial/aws-lambda
/tutorial/modeling-bson-data
/tutorial/stable-api
151 changes: 151 additions & 0 deletions docs/tutorial/aws-lambda.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
==============================
Deploy to AWS Lambda with Bref
==============================

.. contents:: On this page
:local:
:backlinks: none
:depth: 2
:class: singlecol

Overview
--------

`Bref <https://bref.sh>`__ lets you deploy serverless PHP applications on AWS Lambda.
In this tutorial, you will deploy a simple PHP application with the MongoDB PHP extension,
and connect to an Atlas cluster using AWS IAM authentication.

Prerequisites
--------------

To deploy to AWS Lambda by using Bref, you must have the following components set up:

- AWS account with access keys
- Serverless Framework

To learn how to set these up, follow the `Setup tutorial <https://bref.sh/docs/setup>`__
in the Bref official documentation.

Install the MongoDB extension
-----------------------------

Bref uses Lambda layers to provide the PHP runtime. The ``bref`` layer is compiled
with PHP and a few extensions. Other extensions, like ``mongodb``, are available
in additional layers.

Start by creating a new directory for your project and install the required MongoDB
and Bref dependencies.

.. code-block:: none

$ mkdir bref-mongodb-app && cd bref-mongodb-app
$ composer init
$ composer require bref/bref bref/extra-php-extensions mongodb/mongodb

Then initialize the serverless configuration using the ``bref`` command.

.. code-block:: none

$ vendor/bin/bref init


After this series of commands, you should have this files:

- ``composer.json`` for PHP dependencies installed in the ``vendor`` directory
- ``index.php`` a sample webpage
- ``serverless.yml`` for the configuration of the deployment

To validate your setup, try deploying this default application. This outputs
a URL that renders a webpage with the Bref logo:

.. code-block:: none

$ serverless deploy


Now that you have initialized the project, you will add the ``mongodb`` extension.
Locate the "Serverless config" name in the list of extensions provided by
`bref/extra-php-extension <https://github.com/brefphp/extra-php-extensions>`__.
Add it to the ``layers`` of the function in ``serverless.yaml``, this file
will look like this:

.. code-block:: yaml

plugins:
- ./vendor/bref/bref
- ./vendor/bref/extra-php-extensions

functions:
api:
handler: index.php
runtime: php-83-fpm
layers:
- ${bref-extra:mongodb-php-83}



Let's use the MongoDB driver with a web page that list planets from the Atlas
`sample dataset <https://www.mongodb.com/docs/atlas/sample-data/>`__.
Replace the contents of ``index.php`` with the following:

.. literalinclude:: /examples/aws-lambda/index.php
:language: php


Redeploy the application with the new ``index.php``:

.. code-block:: none

$ serverless deploy


The application will display an error message because the ``MONGODB_URI``
environment variable has not yet been set. We'll look at how to set this
variable in the next section.

AWS Credentials
---------------

Atlas supports passwordless authentication with AWS credentials. In any Lambda function,
AWS sets environment variables that contains the access token and secret token with
the role assigned to deployed function.

1. Open the Lambda function in the AWS console
2. In :guilabel:`Configuration > Permission`, copy the :guilabel:`Role name`
3. Add this role to your Atlas cluster with the built-in Role: "Read and write any database"

To learn how to set up unified AWS access, see `Set Up Unified AWS Access
<https://www.mongodb.com/docs/atlas/security/set-up-unified-aws-access/>`__
in the MongoDB Atlas documentation.

Now that the permissions have been configured, the Lambda function is allowed to access
your Atlas cluster. You can configure your application with the Atlas endpoint.

Access to Atlas clusters is also restricted by IP address. Since the range of IP that comes
from AWS is very wide, you can `allow access from everywhere
<https://www.mongodb.com/docs/atlas/security/ip-access-list/>`__.

.. note::

Using VPC Peering is recommended in order to isolate your Atlas cluster from Internet.
This requires the Lambda function to be deployed in this AWS VPC.

Find the connection URI in the Atlas UI :guilabel:`Atlas > Deployment > Database > Connect`.
Select :guilabel:`3. AWS IAM`.
Remove the ``<AWS access key>:<AWS secret key>`` part from the URI, the credentials
will be read from environment variables.

Update the ``serverless.yml`` file to pass the environment variable ``MONGODB_URI``.

.. code-block:: yaml

provider:
environment:
MONGODB_URI: "mongodb+srv://cluster0.example.mongodb.net/?authSource=%24external&authMechanism=MONGODB-AWS&retryWrites=true&w=majority"

Finally, deploy with the new configuration. After deployment completes, you can
access the function URL and see the list of planets from your Atlas cluster.

.. code-block:: none

$ serverless deploy
8 changes: 8 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@

<!-- Disable forbidden annotation sniff as excluding @api from the list doesn't work -->
<exclude name="SlevomatCodingStandard.Commenting.ForbiddenAnnotations.AnnotationForbidden" />

<!-- Example file using HTML templating -->
<exclude name="Generic.Files.InlineHTML.Found">
<exclude-pattern>docs/examples/*/index.php</exclude-pattern>
</exclude>
<exclude name="SlevomatCodingStandard.ControlStructures.BlockControlStructureSpacing.IncorrectLinesCountAfterControlStructure">
<exclude-pattern>docs/examples/*/index.php</exclude-pattern>
</exclude>
</rule>


Expand Down

0 comments on commit af89a5e

Please sign in to comment.