DEV Community

Cloud Native Buildpack for Bref: build your app for Lambda in one command

I've been deploying PHP applications to AWS Lambda with Bref for a while now. Since I'm a Terraform fan, I very quickly parted with @mnapoli's serverless.yml approach, in favour a Terraform + container-based Lambdas.

Here, the Dockerfile approach works, but it's verbose: a typical multi-stage Dockerfile for a Symfony app on Lambda is 100+ lines of repetitive infrastructure code.

Recently, Cloud Native Buildpacks (CNB) caught my attention. Their promise is to turn source code into container images without a Dockerfile, with built-in layer caching and a standardized build/run separation. The question was: could this work for Lambda?

The challenge

Lambda container images have specific requirements that don't align perfectly with the CNB model:

  • Lambda expects the app at /var/task (a reserved, non-overridable path)
  • Lambda needs a specific entrypoint (/lambda-entrypoint.sh for Bref)
  • The CNB lifecycle adds its own launcher binary that Lambda doesn't understand
  • Bref base images use Amazon Linux with stripped-down package managers

None of these are showstoppers, but they required creative solutions.

What my buildpack does

Given a PHP project with bref/bref in its composer.json, the buildpack handles everything:

  1. Detects the app (composer.json + bref dependency)
  2. Installs PHP extensions (via crane download or from-source compilation)
  3. Runs composer install with production optimizations
  4. Configures OPcache for Lambda cold starts
  5. Detects Symfony and warms the cache
  6. Produces a Lambda-ready container image

The entire configuration is driven by environment variables:

make lambda \
  TEST_APP_PATH=./my-symfony-app \
  LAMBDA_IMAGE=my-app \
  BP_BREF_RUNTIME=fpm \
  BP_BREF_EXTENSIONS=redis,gd,soap \
  BP_OPCACHE_JIT=true
Enter fullscreen mode Exit fullscreen mode

Compare that to 120 lines of multi-stage Dockerfile with extension compilation, vendor optimization, cache warmup, and OPcache tuning.

Testing it for real

I deployed the Symfony Demo application to Lambda using the buildpack. Same app, same database, same environment variables as the existing layer-based deployment. Only change: it's just built with pack build instead of docker build and a long multi-stage Docker file.

It works. The function URL serves the app correctly, Symfony cache is pre-warmed, and the second build reuses all cached layers (vendor, opcache config) making rebuilds near-instant when only application code changes.

I also tested extension compilation: ftp and soap compile successfully from PHP source on ARM64 during the build step, with proper shared library dependency resolution via Bref's copy-dependencies.php.

What's not handled by the buildpack

The buildpack builds your app into a Lambda container image. It does not:

  • Set up your Symfony app for Bref (you still need BrefKernel, trusted_proxies, etc.)
  • Serve static assets (CSS/JS need CloudFront + S3, same as any Bref deployment)
  • Replace your IaC (you still need Terraform/CDK/Serverless to create the Lambda function)

It replaces the Dockerfile and the build process, not the infrastructure or app configuration.

Current state

The buildpack is published and usable today:

  • GitHub: https://github.com/psantus/bref-buildpack
  • Docker Hub: psantus/bref-buildpack:0.2.0
  • CNB Registry: bref/php-lambda (registered at registry.buildpacks.io)
  • CI: passing on GitHub Actions
  • Tested: Symfony Demo running on Lambda ARM64 (Graviton) via function URL

It supports PHP 8.2/8.3/8.4, ARM and x86 architectures, extension compilation from source, all 40+ bref-extra extensions (x86) or compile-from-source (ARM), Symfony auto-detection, composer caching, OPcache/JIT configuration, and vendor shrinking.

Try it

brew install buildpacks/tap/pack
git clone https://github.com/psantus/bref-buildpack
cd bref-buildpack
make lambda TEST_APP_PATH=/path/to/your/php/app LAMBDA_IMAGE=my-lambda BP_BREF_EXTENSIONS=gd,redis
Enter fullscreen mode Exit fullscreen mode

The resulting image is ready to push to ECR and deploy to Lambda.

Top comments (0)