{"id":19289824,"url":"https://github.com/brefphp/aws-lambda-layers","last_synced_at":"2026-02-26T12:06:10.397Z","repository":{"id":61742597,"uuid":"552058383","full_name":"brefphp/aws-lambda-layers","owner":"brefphp","description":"Bref scripts to build AWS Lambda layers","archived":false,"fork":false,"pushed_at":"2026-02-10T12:43:17.000Z","size":1615,"stargazers_count":42,"open_issues_count":5,"forks_count":29,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-02-10T17:07:51.505Z","etag":null,"topics":["aws-lambda","bref","php"],"latest_commit_sha":null,"homepage":"https://bref.sh/docs/runtimes/","language":"Dockerfile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brefphp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"mnapoli","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":"https://bref.sh/#enterprise"}},"created_at":"2022-10-15T18:10:12.000Z","updated_at":"2026-02-10T12:47:27.000Z","dependencies_parsed_at":"2023-10-17T12:14:43.544Z","dependency_job_id":"3ffbc70a-2884-4e8b-9859-f18d2e32c26b","html_url":"https://github.com/brefphp/aws-lambda-layers","commit_stats":null,"previous_names":[],"tags_count":100,"template":false,"template_full_name":null,"purl":"pkg:github/brefphp/aws-lambda-layers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brefphp%2Faws-lambda-layers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brefphp%2Faws-lambda-layers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brefphp%2Faws-lambda-layers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brefphp%2Faws-lambda-layers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brefphp","download_url":"https://codeload.github.com/brefphp/aws-lambda-layers/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brefphp%2Faws-lambda-layers/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29858461,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-26T08:51:08.701Z","status":"ssl_error","status_checked_at":"2026-02-26T08:50:19.607Z","response_time":89,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws-lambda","bref","php"],"created_at":"2024-11-09T22:17:18.508Z","updated_at":"2026-02-26T12:06:10.385Z","avatar_url":"https://github.com/brefphp.png","language":"Dockerfile","funding_links":["https://github.com/sponsors/mnapoli","https://bref.sh/#enterprise"],"categories":[],"sub_categories":[],"readme":"# PHP layers for AWS Lambda\n\n⚠️⚠️⚠️\n\n\u003e **Warning**\n\u003e **You are probably in the wrong place.**\n\nIf you are new to PHP on Lambda or Bref, **check out [bref.sh](https://bref.sh) instead**.\n\n⚠️⚠️⚠️\n\nThis project is a low-level internal piece of the Bref project. It contains the scripts to build the AWS Lambda layers and Docker images.\n\n---\n\n## Contributing\n\nThank you for diving into this very complex part of Bref.\n\nIf you are submitting a pull request to this repository, you probably want to test your changes:\n\n1. Build the Docker images and the Lambda layers (zip files) locally (to make sure it works).\n2. Run the test scripts.\n3. Publish the Lambda layers to your AWS account and test them in a real Lambda.\n\n**For minor changes** (e.g. upgrading a version) it is faster and easier to open a pull request. The layers will be built faster in CI and the test results will be available in a few minutes.\n\n### Requirements\n\n- `make`\n- `zip`\n- Docker\n- AWS CLI (if publishing layers)\n- AWS credentials set up locally (if publishing layers)\n\n### Building\n\n\u003e **Warning:**\n\u003e\n\u003e On macOS, do not enable [the experimental Rosetta emulation](https://docs.docker.com/desktop/release-notes/#4160). This causes a Segmentation Fault when running `php-fpm` in the Docker images (as of January 2023, this may have been fixed since).\n\nYou can build Docker images and Lambda layers locally:\n\n```sh\n# Make x86 layers (the default)\nmake\n\n# Make ARM layers\nmake CPU=arm\n```\n\nIt will create the Docker images on your machine, and generate the Lambda layer zip files in `./output`. It takes some time to build the Docker images (especially to build the images on the other platform, e.g. the ARM images if you are on an Intel processor).\n\n### Testing\n\nAfter building the images, run the automated tests:\n\n```sh\nmake test\n# and/or\nmake test CPU=arm\n```\n\n\u003e **Note**\n\u003e If automated tests fail, you can test layers manually using Docker. Check out [the README in `tests/`](tests/README.md).\n\n### Uploading layers\n\nYou can build everything _and_ upload Lambda layers to your AWS account. You will need to set up local AWS credentials. The following environment variables are recognized:\n\n- `AWS_PROFILE` (optional): an AWS profile to use (instead of the default one).\n- `ONLY_REGION` (optional): if set, layers will only be published to this region, instead of _all_ regions (useful for testing).\n\nYou can set those by creating a `.env` file:\n\n```sh\ncp .env.example .env \n\n# Now edit the .env file\n\n# Then build layers:\nmake\nmake CPU=arm\n\n# Then publish layers:\nmake upload-layers\nmake upload-layers CPU=arm\n```\n\nThe published Lambda layers will be public (they are readonly anyway). You can find them in your AWS console (AWS Lambda service). Feel free to delete them afterwards.\n\n### Debugging\n\nIf you ever need to check out the content of a layer, you can start a `bash` terminal inside the Docker image:\n\n```sh\ndocker run --rm -it --entrypoint=bash bref/php-84\n```\n\n\u003e **Note:**\n\u003e \n\u003e `ldd` is a linux utility that will show libraries (`.so` files) used by a binary/library. For example: `ldd /opt/bin/php` or `ldd /opt/bref/extensions/curl.so`. That helps to make sure we include all the libraries needed by PHP extensions in the layers.\n\u003e \n\u003e However, `ldd` fails when running on another CPU architecture. So instead of `ldd`, we can use `LD_TRACE_LOADED_OBJECTS=1 /opt/bin/php` (see https://stackoverflow.com/a/35905007/245552).\n\n### Supporting a new PHP version\n\nThe general idea is to copy `php-82` into `php-83`. Search/replace `php-82` with `php-83`, update the PHP version, update the `Makefile`, and adapt anything else if needed.\n\n### Supporting new regions\n\nCheck out `utils/lambda-publish/Makefile` to add more regions.\n\n## How this repository works\n\n### Repository workflow\n\n1. A PR is opened on this repository.\n    - GitHub Actions will build the layers and test them (but not publish them).\n2. The PR is merged by a Bref maintainer.\n3. A new release is tagged by a Bref maintainer.\n4. GitHub Actions will build the layers, test them, and publish the layers and Docker images.\n5. The \"update layer versions\" job in [brefphp/bref](https://github.com/brefphp/bref) will be triggered automatically.\n    - A pull request will be opened with an updated `layers.json` file.\n    - A Bref maintainer can then merge the PR and manually release a new Bref version.\n6. The \"update layer versions and release\" job in [brefphp/layers.js](https://github.com/brefphp/layers.js) will be triggered automatically.\n    - The `layers.json` file will be updated with new layer versions.\n    - A new GitHub tag and release will be created.\n    - A new release of the `@bref.sh/layers` NPM package will be published.\n\n### How Lambda layers work?\n\nIn a nutshell, a Lambda Layer is a `zip` file. Its content is extracted to `/opt` when a Lambda starts.\n\nAnything we want to make available in AWS Lambda is possible by preparing the right files and packing them into a layer. To work properly, these files need to be compatible with the Lambda environment. AWS provides Docker images (e.g. `public.ecr.aws/lambda/provided:al2-x86_64`) that replicate it.\n\n### Lambda layers structure\n\n```sh\n/opt/ # where layers are unzipped/can add files\n\n    bin/ # where layers can add binaries\n        php # the PHP binary\n        php-fpm # the PHP-FPM binary (only for FPM layers)\n\n    lib/ # system libraries needed by Bref\n\n    bref/ # custom Bref files\n        extensions/ # PHP extensions\n            ...\n        etc/php/conf.d/ # automatically loaded php.ini files\n            bref.ini\n\n    bootstrap # entrypoint of the runtime\n\n/var/runtime/\n    bootstrap # duplicated entrypoint, used when running in Docker\n\n/var/task # the code of the Lambda function\n    php/conf.d/ # also automatically loaded php.ini files\n```\n\nIn the \"build\" Docker images (used by example to build extra extensions), there is a `/bref/lib-copy/copy-dependencies.php` script that helps automatically copying the system dependencies of a binary or PHP extension. It can be used like so:\n\n```sh\nphp /bref/lib-copy/copy-dependencies.php /opt/bref/extensions/apcu.so /opt/lib\n```\n\nIn Bref v1, we used to manually identify (via `ldd`) and copy these system libraries, but this new script automates everything. It is recommended to use it.\n\n### The php-xx folders\n\nThe Dockerfile attempts at a best-effort to follow a top-down execution process for easier reading.\n\nIt starts from an AWS-provided Docker image and compiles the system libraries that we will need to use to compile PHP (the PHP build requires more recent version than what `yum install` provides, so we need to compile them, which is slow.\n\nThen, PHP is compiled. All the compilation happens in `/tmp`.\n\nWe then copy the PHP binary in `/opt/bin` and all PHP extensions in `/opt/...`. Indeed, `/opt` is the target directory of AWS Lambda layers.\n\nThen, we need to copy to `/opt` all the system libraries (`*.so` files) used by PHP and the extensions. To do so, we have a script that parses all the system dependencies of `/opt/bin/php` and extensions, and automatically copies them to `/opt/lib` (a directory automatically scanned by AWS Lambda).\n\nFinally, for each layer, we re-start from scratch from the empty AWS Lambda Docker images (using `FROM`, i.e. multi-stage builds) and we copy `/opt`. That gives us an \"empty\" Docker images with only `/opt` populated, just like on AWS Lambda when the PHP layers are unzipped.\n\nThat will also let us zip `/opt` to create the layers.\n\n## Design decisions log\n\n### Installing PHP from a distribution\n\n#### First iteration\n\nCompiling PHP is a complex process for the average PHP Developer. It takes a fair amount of time\nand can be cumbersome. Using `remi-collet` as a PHP distributor greatly simplifies and help the\ninstallation process. The code is more readable and approachable. Remi also distribute releases\neven before they are announced on the PHP Internal Mailing List by the Release Manager.\n\nThe biggest downside is that we're no longer in control of compiling new releases whenever we want.\nBut for x86 architecture, we see that using remi-collet will not be a problem for this.\nWe can see the impact of this on arm64 (Graviton2 Support). Since remi-collet doesn't distribute arm64,\nwe may have to rely on `amazon-linux-extras`, which is 5 months behind (as of this writing) with PHP 8.0.8.\n\nUseful links:\n\n- https://blog.remirepo.net/pages/English-FAQ#scl\n- https://rpms.remirepo.net/wizard/\n\n#### Second iteration\n\nWe discovered an issue with using Remi's built images ([#42](https://github.com/brefphp/aws-lambda-layers/issues/42)): HTTP2 support was not compiled in CURL. Remi's packages explicitly don't intent to support it, and our only choice is to compile PHP (it's not an extension that can be installed after the fact).\n\nThe previous decision (use Remi's repo) is reverted during Bref v2's beta and we go back to compiling PHP from scratch.\n\nSome benefits:\n\n- We can have identical compilation scripts between x86 and ARM, which simplifies the code a lot\n- We can provide recent PHP versions for ARM, including PHP 8.2 (wasn't supported by Amazon Linux Extra before)\n- We have identical system libraries and dependencies on x86 and ARM, which should avoid weird differences and bugs\n\n##### Bundling extensions\n\nWhile developing a new Runtime, the first attempt was to provide an \"alpine-like\" Bref Layer: only the PHP\nbinary and no extension (or minimal extensions) installed. This turned out to slow down the process\nby a big factor because every layer needs to be compiled for multiple PHP versions and deployed\nacross 21 AWS Region (at this time). Except for php-intl, most extensions are extremely small and lightweight.\nThe benefits of maintaining a lightweight layer long-term didn't outweigh the costs at this time.\n\n##### Variables vs Repetitive Code\n\nBefore landing on the current architecture, there was several attempts (9 to be exact) on a back-and-forth\nbetween more environment variables vs more repetitive code. Environment variables grows complexity because\nthey require contributors to understand how they intertwine with each other. We have layers, php version and\nCPU architecture. A more \"reusable\" Dockerfile or docker compose requires a more complex Makefile. In contrast,\na simpler and straight-forward Makefile requires more code duplication for Docker and Docker Compose.\nThe current format makes it so that old PHP layers can easily be removed by dropping an entire folder\nand a new PHP Version can be added by copying an existing folder and doing search/replace on the\nPHP version. It's a hard balance between a process that allows parallelization, code reusability and\nreadability.\n\n##### Layer Publishing\n\nIt would have been ideal to be able to upload the layers to a single S3 folder and then \"publish\" a new layer by pointing it to the existing S3Bucket/S3Key. However, AWS Lambda does not allow publishing layers from a bucket in another region. Layers must be published on each region individually, so instead we upload the zip files for every layer published.\n\nParallelization of all regions at once often leads to network crashing. The strategy applied divides AWS\nregions in chunks (7 to be precise) and tries to publish 7 layers at a time.\n\n##### AWS CodeBuild vs GitHub Actions\n\nAWS CodeBuild was used for Bref v1 builds, as it lets us use large instances to build faster. Bref 1 layers took an hour to build. Additionally, using CodeBuild allowed to avoid using AWS access keys to publish layers.\n\nFor Bref v2, we now build in GitHub Actions because it's simpler, entirely public and easier to follow for maintainers and contributors.\n\nTo make builds 10× to 20× faster, we use https://depot.dev thanks who generously offered to support Bref for free ❤️\n\nAdditionally, using OIDC we can authorize this repository to publish into the AWS account with very restricted permissions _without_ using AWS access keys (assume role, just like CodeBuild).\n\n##### Automation tests\n\nThe `tests` folder contains multiple PHP scripts that are executed inside a Docker container that Bref builds. These scripts are supposed to ensure that the PHP version is expected, PHP extensions are correctly installed and available and PHP is correctly configured. Some acceptance tests uses AWS Runtime Interface Emulator (RIE) to test whether a Lambda invocation is expected to work.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrefphp%2Faws-lambda-layers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrefphp%2Faws-lambda-layers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrefphp%2Faws-lambda-layers/lists"}