├── .dockerignore ├── .env.example ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature-or-improvement.md ├── aws │ ├── README.md │ └── github-role.yml ├── pull_request_template.md └── workflows │ ├── release.yml │ └── tests.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── depot.json ├── docker-bake.hcl ├── layers ├── bootstrap.php ├── console │ ├── Dockerfile │ ├── README.md │ └── bootstrap.sh ├── fpm-dev │ ├── Dockerfile │ └── bref-entrypoint.sh ├── fpm │ ├── bootstrap.sh │ ├── bref.ini │ └── php-fpm.conf └── function │ ├── bootstrap.sh │ └── bref.ini ├── output └── .gitignore ├── php-80 └── Dockerfile ├── php-81 └── Dockerfile ├── php-82 └── Dockerfile ├── php-83 └── Dockerfile ├── php-84 └── Dockerfile ├── tests ├── .gitignore ├── Makefile ├── README.md ├── composer.json ├── php │ └── conf.d │ │ └── test_4_php.ini ├── test_1_binary.php ├── test_2_extensions.php ├── test_3_manual_enabling_extensions.php ├── test_3_manual_extensions.ini ├── test_4_function_handler.php ├── test_4_function_invocation.php ├── test_5_event.json ├── test_5_fpm_handler.php ├── test_5_fpm_invocation.php ├── test_6_console_handler.php ├── test_6_console_invocation.php ├── test_7_custom_ini_scan_dir.php └── utils.php └── utils ├── docker-zip-dir.sh ├── lambda-publish ├── Makefile └── publish.sh └── lib-copy ├── Makefile ├── copy-dependencies.php ├── docker-compose.yml ├── libs-arm.txt └── libs-x86.txt /.dockerignore: -------------------------------------------------------------------------------- 1 | .github/ 2 | aws/ 3 | output/ 4 | tests/ 5 | .env 6 | .env.example 7 | .gitignore 8 | *Makefile 9 | *.yml 10 | *.md 11 | *.png 12 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # Uncomment if you want to deploy layers only to a single region (for example to test) 2 | #ONLY_REGION=us-east-1 3 | 4 | # If you want to use a specific AWS profile, uncomment the following line and set the profile name 5 | #AWS_PROFILE=your-profile-name 6 | 7 | # Limit the parallelization of layer publication. 8 | # Default is 7, we recommend a lower number when publishing from a laptop. 9 | MAX_PARALLEL_PUBLISH=3 10 | 11 | # In the CI and on local machines in the core team we build using https://depot.dev 12 | # as it is much faster to build cross-platform images. 13 | # Do not uncomment this line, unless you have a depot.dev account. 14 | #USE_DEPOT=1 15 | 16 | # Uncomment this line if you want to add custom flags to the PHP compilation process. 17 | # For example, you can add the flag --enable-zts to complile PHP with ZTS enabled 18 | #PHP_COMPILATION_FLAGS= 19 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: mnapoli # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: 'https://bref.sh/#enterprise' # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report a bug in Bref 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Description:** 11 | 12 | 13 | 14 | **How to reproduce:** 15 | 16 | 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Community support 4 | url: https://github.com/brefphp/bref/discussions?discussions_q=category%3ASupport 5 | about: Please ask and answer questions in GitHub Discussions. 6 | - name: Professional support 7 | url: https://bref.sh/#enterprise 8 | about: Get in touch with Null, the company behind Bref. 9 | - name: Sponsor a feature 10 | url: https://bref.sh/#enterprise 11 | about: Sponsor the development of a new feature you want to see in Bref. 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-or-improvement.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature or improvement 3 | about: Suggest a feature or improvement 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/aws/README.md: -------------------------------------------------------------------------------- 1 | ## Setup 2 | 3 | ### Authorize GitHub Actions to deploy to AWS 4 | 5 | In order to let GitHub Actions upload layers to AWS, we authorize GitHub via [OIDC](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services) instead of hardcoded AWS access keys. 6 | 7 | This needs to be done once in the AWS console (because no access keys have permissions to deploy via CloudFormation). 8 | 9 | - file: `github-role.yml` 10 | - stack name: github-oidc-provider 11 | - `FullRepoName` parameter: `brefphp/aws-lambda-layers` 12 | -------------------------------------------------------------------------------- /.github/aws/github-role.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | Description: OIDC provider that lets GitHub Actions deploy to AWS 3 | 4 | Parameters: 5 | FullRepoName: 6 | Type: String 7 | 8 | Resources: 9 | Role: 10 | Type: AWS::IAM::Role 11 | Properties: 12 | RoleName: bref-layer-publisher-github-actions 13 | AssumeRolePolicyDocument: 14 | Statement: 15 | - Effect: Allow 16 | Action: sts:AssumeRoleWithWebIdentity 17 | Principal: 18 | Federated: !Ref GithubOidc 19 | Condition: 20 | StringLike: 21 | token.actions.githubusercontent.com:sub: !Sub repo:${FullRepoName}:* 22 | Policies: 23 | - PolicyName: LayerPublisherRole 24 | PolicyDocument: 25 | Statement: 26 | - Effect: Allow 27 | Action: 28 | - lambda:PublishLayerVersion 29 | - lambda:AddLayerVersionPermission 30 | - lambda:GetLayerVersion 31 | - lambda:GetLayerVersionPolicy 32 | - lambda:ListLayers 33 | - lambda:ListLayerVersions 34 | Resource: 35 | - '*' 36 | 37 | GithubOidc: 38 | Type: AWS::IAM::OIDCProvider 39 | Properties: 40 | Url: https://token.actions.githubusercontent.com 41 | ThumbprintList: 42 | - '6938fd4d98bab03faadb97b34396831e3780aea1' 43 | - '1c58a3a8518e8759bf075b76b750d4f2df264fcd' 44 | ClientIdList: 45 | - sts.amazonaws.com 46 | 47 | Outputs: 48 | Role: 49 | Value: !GetAtt Role.Arn 50 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | # This workflow can be manually triggered 5 | workflow_dispatch: 6 | # But the main use case is to release new layers when a release is created 7 | release: 8 | types: [ published ] 9 | 10 | # Necessary to deploy to AWS using OIDC 11 | # https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services 12 | permissions: 13 | id-token: write # This is required for requesting the JWT 14 | contents: read # This is required for actions/checkout 15 | 16 | jobs: 17 | 18 | release: 19 | name: Publish ${{ matrix.cpu }} layers 20 | runs-on: ubuntu-22.04 21 | strategy: 22 | matrix: 23 | cpu: 24 | - x86 25 | - arm 26 | steps: 27 | - uses: actions/checkout@v4 28 | 29 | - name: Get the version 30 | id: get_version 31 | run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} 32 | 33 | # See https://stackoverflow.com/questions/70312490/github-actions-runner-environment-doesnt-build-for-arm-images 34 | - name: Set up QEMU to run ARM images (that were built with Depot) 35 | uses: docker/setup-qemu-action@v3 36 | 37 | - uses: depot/setup-action@v1 38 | 39 | - name: Configure AWS credentials 40 | uses: aws-actions/configure-aws-credentials@v4 41 | with: 42 | role-to-assume: arn:aws:iam::534081306603:role/bref-layer-publisher-github-actions 43 | role-session-name: bref-layer-publisher-github-actions 44 | aws-region: us-east-1 45 | 46 | - name: Configure Docker Hub credentials 47 | uses: docker/login-action@v3 48 | with: 49 | username: ${{ secrets.DOCKER_USERNAME }} 50 | password: ${{ secrets.DOCKER_PASSWORD }} 51 | 52 | - run: make docker-images 53 | env: 54 | CPU: ${{ matrix.cpu }} 55 | USE_DEPOT: 1 56 | DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }} 57 | 58 | - run: make layers 59 | env: 60 | CPU: ${{ matrix.cpu }} 61 | 62 | - run: make test 63 | env: 64 | CPU: ${{ matrix.cpu }} 65 | 66 | - run: make upload-layers 67 | env: 68 | CPU: ${{ matrix.cpu }} 69 | 70 | - run: make upload-to-docker-hub 71 | env: 72 | CPU: ${{ matrix.cpu }} 73 | DOCKER_TAG: ${{ steps.get_version.outputs.VERSION }} 74 | 75 | update-layer-versions: 76 | name: Update layer versions in brefphp/bref 77 | runs-on: ubuntu-22.04 78 | needs: [ release ] 79 | steps: 80 | - name: Trigger layer update in brefphp/bref 81 | uses: actions/github-script@v6 82 | with: 83 | github-token: ${{ secrets.GH_TOKEN_TRIGGER }} 84 | script: | 85 | await github.rest.actions.createWorkflowDispatch({ 86 | owner: 'brefphp', 87 | repo: 'bref', 88 | workflow_id: 'update-layer-versions.yml', 89 | ref: 'master', 90 | inputs: { 91 | release_url: '${{ github.event.release.url }}', 92 | release_html_url: '${{ github.event.release.html_url }}', 93 | release_name: '${{ github.event.release.name }}' 94 | } 95 | }) 96 | 97 | update-layer-js-versions: 98 | name: Update layer versions in brefphp/layers.js 99 | runs-on: ubuntu-22.04 100 | needs: [ release ] 101 | steps: 102 | - name: Trigger release in brefphp/layers.js 103 | uses: actions/github-script@v6 104 | with: 105 | github-token: ${{ secrets.GH_TOKEN_TRIGGER }} 106 | script: | 107 | await github.rest.actions.createWorkflowDispatch({ 108 | owner: 'brefphp', 109 | repo: 'layers.js', 110 | workflow_id: 'release.yml', 111 | ref: 'main' 112 | }) 113 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | branches: [ 'main' ] 6 | pull_request: 7 | branches: [ '*' ] 8 | 9 | permissions: 10 | # allow issuing OIDC tokens, needed for the depot.dev auth 11 | id-token: write 12 | # allow at least reading the repo contents, add other permissions if necessary 13 | contents: read 14 | 15 | jobs: 16 | matrix-prep: 17 | name: Prepare matrix 18 | runs-on: ubuntu-22.04 19 | outputs: 20 | matrix: ${{ steps.set-matrix.outputs.result }} 21 | steps: 22 | - uses: actions/github-script@v6 23 | id: set-matrix 24 | with: 25 | script: | 26 | const matrix = { 27 | cpu: ['x86', 'arm'], 28 | php_version: ['80', '81', '82', '83', '84'], 29 | } 30 | 31 | // If this is a third-party pull request, skip ARM builds 32 | if (context.eventName === 'pull_request') { 33 | const pr = context.payload.pull_request 34 | if (pr.head.repo.full_name !== pr.base.repo.full_name) { 35 | matrix.cpu = ['x86'] 36 | } 37 | } 38 | 39 | return matrix 40 | 41 | tests: 42 | name: Build and tests PHP ${{ matrix.php_version }}, ${{ matrix.cpu }} 43 | runs-on: ubuntu-22.04 44 | needs: matrix-prep 45 | strategy: 46 | fail-fast: false 47 | matrix: ${{ fromJson(needs.matrix-prep.outputs.matrix) }} 48 | steps: 49 | - uses: actions/checkout@v4 50 | 51 | # See https://stackoverflow.com/questions/70312490/github-actions-runner-environment-doesnt-build-for-arm-images 52 | - name: Set up QEMU to run ARM images (that were built with Depot) 53 | uses: docker/setup-qemu-action@v3 54 | 55 | - uses: depot/setup-action@v1 56 | - uses: docker/setup-buildx-action@v3 57 | 58 | # We use this action instead of running `make docker-images-php-XX` directly because it lets us 59 | # use OIDC authentication instead of a secret. Secrets can't be used in pull request builds. 60 | - name: Build Docker images 61 | uses: depot/bake-action@v1 62 | with: 63 | load: true 64 | # If this is a third-party pull request, fall back to the local buildx builder 65 | buildx-fallback: ${{ github.event.pull_request.head.repo.full_name != github.repository }} 66 | env: 67 | CPU: ${{ matrix.cpu }} 68 | CPU_PREFIX: ${{ (matrix.cpu == 'arm') && 'arm-' || '' }} 69 | PHP_VERSION: ${{ matrix.php_version }} 70 | IMAGE_VERSION_SUFFIX: ${{ (matrix.cpu == 'arm') && 'arm64' || 'x86_64' }} 71 | DOCKER_PLATFORM: ${{ (matrix.cpu == 'arm') && 'linux/arm64' || 'linux/amd64' }} 72 | 73 | - name: Test that layers can be exported 74 | run: | 75 | make layer-php-${{ matrix.php_version }} 76 | make layer-php-${{ matrix.php_version }}-fpm 77 | env: 78 | CPU: ${{ matrix.cpu }} 79 | 80 | - name: Test that the "console" layer can be exported 81 | run: make layer-console 82 | if: ${{ matrix.php_version == 80 }} 83 | env: 84 | CPU: ${{ matrix.cpu }} 85 | 86 | - name: Run tests 87 | run: make test-${{ matrix.php_version }} 88 | env: 89 | CPU: ${{ matrix.cpu }} 90 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2024 Matthieu Napoli 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Load .env file if it exists 2 | -include .env 3 | export # export all variables defined in .env 4 | 5 | # Define all the environment variables depending on the CPU 6 | # Set CPU= (empty) to build for x86 7 | # Set CPU=arm to build for ARM 8 | ifeq ($(CPU), arm) # if $CPU=="arm" 9 | $(info "⚠️ Building for ARM") # Print a message 10 | export CPU = arm 11 | export CPU_PREFIX = arm- 12 | export IMAGE_VERSION_SUFFIX = arm64 13 | export DOCKER_PLATFORM = linux/arm64 14 | else 15 | $(info "⚠️ Building for x86") # Print a message 16 | export CPU = x86 17 | export CPU_PREFIX = 18 | export IMAGE_VERSION_SUFFIX = x86_64 19 | export DOCKER_PLATFORM = linux/amd64 20 | endif 21 | 22 | # By default, Docker images are built using `docker buildx bake` 23 | # But we use https://depot.dev in CI (super fast) by setting USE_DEPOT=1 24 | ifeq ($(USE_DEPOT), 1) # if $USE_DEPOT=="1" 25 | $(info "⚠️ Building using depot.dev") # Print a message 26 | export BAKE_COMMAND = depot bake 27 | else 28 | export BAKE_COMMAND = docker buildx bake 29 | endif 30 | 31 | 32 | # Build all Docker images and layers *locally* 33 | # Use this to test your changes 34 | default: docker-images layers 35 | 36 | 37 | # Build Docker images *locally* 38 | docker-images: docker-images-php-80 docker-images-php-81 docker-images-php-82 docker-images-php-83 docker-images-php-84 39 | docker-images-php-%: 40 | PHP_VERSION=$* ${BAKE_COMMAND} --load 41 | 42 | 43 | # Build Lambda layers (zip files) *locally* 44 | layers: layer-php-80 layer-php-81 layer-php-82 layer-php-83 layer-php-84 layer-php-80-fpm layer-php-81-fpm layer-php-82-fpm layer-php-83-fpm layer-php-84-fpm 45 | # Build the console layer only once (x86 and single PHP version) 46 | @if [ ${CPU} = "x86" ]; then \ 47 | $(MAKE) layer-console; \ 48 | fi 49 | layer-console: 50 | ./utils/docker-zip-dir.sh bref/console-zip console 51 | # This rule matches with a wildcard, for example `layer-php-80`. 52 | # The `$*` variable will contained the matched part, in this case `php-80`. 53 | layer-%: 54 | ./utils/docker-zip-dir.sh bref/${CPU_PREFIX}$* ${CPU_PREFIX}$* 55 | 56 | 57 | # Upload the layers to AWS Lambda 58 | # Uses the current AWS_PROFILE. Most users will not want to use this option 59 | # as this will publish all layers to all regions + publish all Docker images. 60 | upload-layers: upload-layers-php-80 upload-layers-php-81 upload-layers-php-82 upload-layers-php-83 upload-layers-php-84 61 | # Upload the console layer only once (x86 and single PHP version) 62 | @if [ ${CPU} = "x86" ]; then \ 63 | LAYER_NAME=console $(MAKE) -C ./utils/lambda-publish publish-parallel; \ 64 | fi 65 | upload-layers-php-%: 66 | # Upload the function layers to AWS 67 | LAYER_NAME=${CPU_PREFIX}php-$* $(MAKE) -C ./utils/lambda-publish publish-parallel 68 | # Upload the FPM layers to AWS 69 | LAYER_NAME=${CPU_PREFIX}php-$*-fpm $(MAKE) -C ./utils/lambda-publish publish-parallel 70 | 71 | 72 | # Publish Docker images to Docker Hub. 73 | upload-to-docker-hub: upload-to-docker-hub-php-80 upload-to-docker-hub-php-81 upload-to-docker-hub-php-82 upload-to-docker-hub-php-83 upload-to-docker-hub-php-84 74 | upload-to-docker-hub-php-%: 75 | # Make sure we have defined the docker tag 76 | (test $(DOCKER_TAG)) && echo "Tagging images with \"${DOCKER_TAG}\"" || echo "You have to define environment variable DOCKER_TAG" 77 | test $(DOCKER_TAG) 78 | 79 | set -e ; \ 80 | for image in \ 81 | "bref/${CPU_PREFIX}php-$*" "bref/${CPU_PREFIX}php-$*-fpm" "bref/${CPU_PREFIX}php-$*-console" \ 82 | "bref/${CPU_PREFIX}build-php-$*" "bref/${CPU_PREFIX}php-$*-fpm-dev"; \ 83 | do \ 84 | docker tag $$image $$image:2 ; \ 85 | docker tag $$image $$image:${DOCKER_TAG} ; \ 86 | docker push $$image:2 ; \ 87 | docker push $$image:${DOCKER_TAG} ; \ 88 | docker push $$image:latest ; \ 89 | done 90 | 91 | 92 | test: test-80 test-81 test-82 test-83 test-84 93 | test-%: 94 | cd tests && $(MAKE) test-$* 95 | 96 | 97 | clean: clean-80 clean-81 clean-82 clean-83 clean-84 98 | # Clear the build cache, else all images will be rebuilt using cached layers 99 | docker builder prune 100 | # Remove zip files 101 | rm -f output/${CPU_PREFIX}*.zip 102 | clean-%: 103 | # Clean Docker images to force rebuilding them 104 | docker image rm --force bref/${CPU_PREFIX}build-php-$* \ 105 | bref/${CPU_PREFIX}php-$* \ 106 | bref/${CPU_PREFIX}php-$*-zip \ 107 | bref/${CPU_PREFIX}php-$*-fpm \ 108 | bref/${CPU_PREFIX}php-$*-fpm-zip \ 109 | bref/${CPU_PREFIX}php-$*-fpm-dev \ 110 | bref/${CPU_PREFIX}php-$*-console 111 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP layers for AWS Lambda 2 | 3 | ⚠️⚠️⚠️ 4 | 5 | > **Warning** 6 | > **You are probably in the wrong place.** 7 | 8 | If you are new to PHP on Lambda or Bref, **check out [bref.sh](https://bref.sh) instead**. 9 | 10 | ⚠️⚠️⚠️ 11 | 12 | This project is a low-level internal piece of the Bref project. It contains the scripts to build the AWS Lambda layers and Docker images. 13 | 14 | --- 15 | 16 | ## Contributing 17 | 18 | Thank you for diving into this very complex part of Bref. 19 | 20 | If you are submitting a pull request to this repository, you probably want to test your changes: 21 | 22 | 1. Build the Docker images and the Lambda layers (zip files) locally (to make sure it works). 23 | 2. Run the test scripts. 24 | 3. Publish the Lambda layers to your AWS account and test them in a real Lambda. 25 | 26 | **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. 27 | 28 | ### Requirements 29 | 30 | - `make` 31 | - `zip` 32 | - Docker 33 | - AWS CLI (if publishing layers) 34 | - AWS credentials set up locally (if publishing layers) 35 | 36 | ### Building 37 | 38 | > **Warning:** 39 | > 40 | > 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). 41 | 42 | You can build Docker images and Lambda layers locally: 43 | 44 | ```sh 45 | # Make x86 layers (the default) 46 | make 47 | 48 | # Make ARM layers 49 | make CPU=arm 50 | ``` 51 | 52 | It 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). 53 | 54 | ### Testing 55 | 56 | After building the images, run the automated tests: 57 | 58 | ```sh 59 | make test 60 | # and/or 61 | make test CPU=arm 62 | ``` 63 | 64 | > **Note** 65 | > If automated tests fail, you can test layers manually using Docker. Check out [the README in `tests/`](tests/README.md). 66 | 67 | ### Uploading layers 68 | 69 | You 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: 70 | 71 | - `AWS_PROFILE` (optional): an AWS profile to use (instead of the default one). 72 | - `ONLY_REGION` (optional): if set, layers will only be published to this region, instead of _all_ regions (useful for testing). 73 | 74 | You can set those by creating a `.env` file: 75 | 76 | ```sh 77 | cp .env.example .env 78 | 79 | # Now edit the .env file 80 | 81 | # Then build layers: 82 | make 83 | make CPU=arm 84 | 85 | # Then publish layers: 86 | make upload-layers 87 | make upload-layers CPU=arm 88 | ``` 89 | 90 | The 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. 91 | 92 | ### Debugging 93 | 94 | If you ever need to check out the content of a layer, you can start a `bash` terminal inside the Docker image: 95 | 96 | ```sh 97 | docker run --rm -it --entrypoint=bash bref/php-80 98 | ``` 99 | 100 | > **Note:** 101 | > 102 | > `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. 103 | > 104 | > 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). 105 | 106 | ### Supporting a new PHP version 107 | 108 | The 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. 109 | 110 | ### Supporting new regions 111 | 112 | Check out `utils/lambda-publish/Makefile` to add more regions. 113 | 114 | ## How this repository works 115 | 116 | ### Repository workflow 117 | 118 | 1. A PR is opened on this repository. 119 | - GitHub Actions will build the layers and test them (but not publish them). 120 | 2. The PR is merged by a Bref maintainer. 121 | 3. A new release is tagged by a Bref maintainer. 122 | 4. GitHub Actions will build the layers, test them, and publish the layers and Docker images. 123 | 5. The "update layer versions" job in [brefphp/bref](https://github.com/brefphp/bref) will be triggered automatically. 124 | - A pull request will be opened with an updated `layers.json` file. 125 | - A Bref maintainer can then merge the PR and manually release a new Bref version. 126 | 6. The "update layer versions and release" job in [brefphp/layers.js](https://github.com/brefphp/layers.js) will be triggered automatically. 127 | - The `layers.json` file will be updated with new layer versions. 128 | - A new GitHub tag and release will be created. 129 | - A new release of the `@bref.sh/layers` NPM package will be published. 130 | 131 | ### How Lambda layers work? 132 | 133 | In a nutshell, a Lambda Layer is a `zip` file. Its content is extracted to `/opt` when a Lambda starts. 134 | 135 | Anything 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. 136 | 137 | ### Lambda layers structure 138 | 139 | ```sh 140 | /opt/ # where layers are unzipped/can add files 141 | 142 | bin/ # where layers can add binaries 143 | php # the PHP binary 144 | php-fpm # the PHP-FPM binary (only for FPM layers) 145 | 146 | lib/ # system libraries needed by Bref 147 | 148 | bref/ # custom Bref files 149 | extensions/ # PHP extensions 150 | ... 151 | php-fpm-runtime/ # the built-in FPM runtime 152 | etc/php/conf.d/ # automatically loaded php.ini files 153 | bref.ini 154 | bootstrap.php # (for the function layer only) 155 | 156 | bootstrap # entrypoint of the runtime 157 | 158 | /var/runtime/ 159 | bootstrap # duplicated entrypoint, used when running in Docker 160 | 161 | /var/task # the code of the Lambda function 162 | php/conf.d/ # also automatically loaded php.ini files 163 | ``` 164 | 165 | In 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: 166 | 167 | ```sh 168 | php /bref/lib-copy/copy-dependencies.php /opt/bref/extensions/apcu.so /opt/lib 169 | ``` 170 | 171 | In 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. 172 | 173 | ### The php-xx folders 174 | 175 | The Dockerfile attempts at a best-effort to follow a top-down execution process for easier reading. 176 | 177 | It 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. 178 | 179 | Then, PHP is compiled. All the compilation happens in `/tmp`. 180 | 181 | We then copy the PHP binary in `/opt/bin` and all PHP extensions in `/opt/...`. Indeed, `/opt` is the target directory of AWS Lambda layers. 182 | 183 | Then, 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). 184 | 185 | Finally, 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. 186 | 187 | That will also let us zip `/opt` to create the layers. 188 | 189 | ## Design decisions log 190 | 191 | ### Installing PHP from a distribution 192 | 193 | #### First iteration 194 | 195 | Compiling PHP is a complex process for the average PHP Developer. It takes a fair amount of time 196 | and can be cumbersome. Using `remi-collet` as a PHP distributor greatly simplifies and help the 197 | installation process. The code is more readable and approachable. Remi also distribute releases 198 | even before they are announced on the PHP Internal Mailing List by the Release Manager. 199 | 200 | The biggest downside is that we're no longer in control of compiling new releases whenever we want. 201 | But for x86 architecture, we see that using remi-collet will not be a problem for this. 202 | We can see the impact of this on arm64 (Graviton2 Support). Since remi-collet doesn't distribute arm64, 203 | we may have to rely on `amazon-linux-extras`, which is 5 months behind (as of this writing) with PHP 8.0.8. 204 | 205 | Useful links: 206 | 207 | - https://blog.remirepo.net/pages/English-FAQ#scl 208 | - https://rpms.remirepo.net/wizard/ 209 | 210 | #### Second iteration 211 | 212 | We 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). 213 | 214 | The previous decision (use Remi's repo) is reverted during Bref v2's beta and we go back to compiling PHP from scratch. 215 | 216 | Some benefits: 217 | 218 | - We can have identical compilation scripts between x86 and ARM, which simplifies the code a lot 219 | - We can provide recent PHP versions for ARM, including PHP 8.2 (wasn't supported by Amazon Linux Extra before) 220 | - We have identical system libraries and dependencies on x86 and ARM, which should avoid weird differences and bugs 221 | 222 | ##### Bundling extensions 223 | 224 | While developing a new Runtime, the first attempt was to provide an "alpine-like" Bref Layer: only the PHP 225 | binary and no extension (or minimal extensions) installed. This turned out to slow down the process 226 | by a big factor because every layer needs to be compiled for multiple PHP versions and deployed 227 | across 21 AWS Region (at this time). Except for php-intl, most extensions are extremely small and lightweight. 228 | The benefits of maintaining a lightweight layer long-term didn't outweigh the costs at this time. 229 | 230 | ##### Variables vs Repetitive Code 231 | 232 | Before landing on the current architecture, there was several attempts (9 to be exact) on a back-and-forth 233 | between more environment variables vs more repetitive code. Environment variables grows complexity because 234 | they require contributors to understand how they intertwine with each other. We have layers, php version and 235 | CPU architecture. A more "reusable" Dockerfile or docker compose requires a more complex Makefile. In contrast, 236 | a simpler and straight-forward Makefile requires more code duplication for Docker and Docker Compose. 237 | The current format makes it so that old PHP layers can easily be removed by dropping an entire folder 238 | and a new PHP Version can be added by copying an existing folder and doing search/replace on the 239 | PHP version. It's a hard balance between a process that allows parallelization, code reusability and 240 | readability. 241 | 242 | ##### Layer Publishing 243 | 244 | It 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. 245 | 246 | Parallelization of all regions at once often leads to network crashing. The strategy applied divides AWS 247 | regions in chunks (7 to be precise) and tries to publish 7 layers at a time. 248 | 249 | ##### AWS CodeBuild vs GitHub Actions 250 | 251 | AWS 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. 252 | 253 | For Bref v2, we now build in GitHub Actions because it's simpler, entirely public and easier to follow for maintainers and contributors. 254 | 255 | To make builds 10× to 20× faster, we use https://depot.dev thanks who generously offered to support Bref for free ❤️ 256 | 257 | Additionally, 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). 258 | 259 | ##### Automation tests 260 | 261 | The `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. 262 | -------------------------------------------------------------------------------- /depot.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "t048vfb17n" 3 | } 4 | -------------------------------------------------------------------------------- /docker-bake.hcl: -------------------------------------------------------------------------------- 1 | group "default" { 2 | targets = ["build-php", "php", "php-fpm", "console-zip", "console", "php-fpm-dev"] 3 | } 4 | 5 | variable "CPU" { 6 | default = "x86" 7 | } 8 | variable "CPU_PREFIX" { 9 | default = "" 10 | } 11 | variable "PHP_VERSION" { 12 | default = "80" 13 | } 14 | variable "IMAGE_VERSION_SUFFIX" { 15 | default = "x86_64" 16 | } 17 | variable "DOCKER_PLATFORM" { 18 | default = "linux/amd64" 19 | } 20 | variable "PHP_COMPILATION_FLAGS" { 21 | default = "" 22 | } 23 | 24 | target "build-php" { 25 | dockerfile = "php-${PHP_VERSION}/Dockerfile" 26 | target = "build-environment" 27 | tags = ["bref/${CPU_PREFIX}build-php-${PHP_VERSION}"] 28 | args = { 29 | "IMAGE_VERSION_SUFFIX" = "${IMAGE_VERSION_SUFFIX}" 30 | "PHP_COMPILATION_FLAGS" = "${PHP_COMPILATION_FLAGS}" 31 | } 32 | platforms = ["${DOCKER_PLATFORM}"] 33 | } 34 | 35 | target "php" { 36 | dockerfile = "php-${PHP_VERSION}/Dockerfile" 37 | target = "function" 38 | tags = ["bref/${CPU_PREFIX}php-${PHP_VERSION}"] 39 | args = { 40 | "IMAGE_VERSION_SUFFIX" = "${IMAGE_VERSION_SUFFIX}" 41 | "PHP_COMPILATION_FLAGS" = "${PHP_COMPILATION_FLAGS}" 42 | } 43 | contexts = { 44 | "bref/${CPU_PREFIX}build-php-${PHP_VERSION}" = "target:build-php" 45 | } 46 | platforms = ["${DOCKER_PLATFORM}"] 47 | } 48 | 49 | target "php-fpm" { 50 | dockerfile = "php-${PHP_VERSION}/Dockerfile" 51 | target = "fpm" 52 | tags = ["bref/${CPU_PREFIX}php-${PHP_VERSION}-fpm"] 53 | args = { 54 | "IMAGE_VERSION_SUFFIX" = "${IMAGE_VERSION_SUFFIX}" 55 | } 56 | contexts = { 57 | "bref/${CPU_PREFIX}build-php-${PHP_VERSION}" = "target:build-php" 58 | "bref/${CPU_PREFIX}php-${PHP_VERSION}" = "target:php" 59 | } 60 | platforms = ["${DOCKER_PLATFORM}"] 61 | } 62 | 63 | target "console-zip" { 64 | context = "layers/console" 65 | target = "console-zip" 66 | tags = ["bref/console-zip"] 67 | args = { 68 | PHP_VERSION = "${PHP_VERSION}" 69 | CPU_PREFIX = "${CPU_PREFIX}" 70 | } 71 | platforms = ["${DOCKER_PLATFORM}"] 72 | } 73 | 74 | target "console" { 75 | context = "layers/console" 76 | target = "console" 77 | tags = ["bref/${CPU_PREFIX}php-${PHP_VERSION}-console"] 78 | args = { 79 | PHP_VERSION = "${PHP_VERSION}" 80 | CPU_PREFIX = "${CPU_PREFIX}" 81 | } 82 | contexts = { 83 | "bref/${CPU_PREFIX}build-php-${PHP_VERSION}" = "target:build-php" 84 | "bref/${CPU_PREFIX}php-${PHP_VERSION}" = "target:php" 85 | } 86 | platforms = ["${DOCKER_PLATFORM}"] 87 | } 88 | 89 | target "php-fpm-dev" { 90 | context = "layers/fpm-dev" 91 | tags = ["bref/${CPU_PREFIX}php-${PHP_VERSION}-fpm-dev"] 92 | args = { 93 | PHP_VERSION = "${PHP_VERSION}" 94 | CPU_PREFIX = "${CPU_PREFIX}" 95 | } 96 | contexts = { 97 | "bref/${CPU_PREFIX}build-php-${PHP_VERSION}" = "target:build-php" 98 | "bref/${CPU_PREFIX}php-${PHP_VERSION}" = "target:php" 99 | "bref/${CPU_PREFIX}php-${PHP_VERSION}-fpm" = "target:php-fpm" 100 | "bref/local-api-gateway" = "docker-image://bref/local-api-gateway:latest" 101 | } 102 | platforms = ["${DOCKER_PLATFORM}"] 103 | } 104 | -------------------------------------------------------------------------------- /layers/bootstrap.php: -------------------------------------------------------------------------------- 1 | &1 19 | else 20 | # A wrapper script is configured 21 | # See https://docs.aws.amazon.com/lambda/latest/dg/runtimes-modify.html#runtime-wrapper 22 | # NOTE: EXPERIMENTAL FEATURE, DO NOT USE!!! 23 | # Note: If you do use it, open an issue or GitHub discussion or Slack thread 24 | # and let us know why it's useful to you, we might turn it into an official feature 25 | "${EXPERIMENTAL_AWS_LAMBDA_EXEC_WRAPPER}" php "/opt/bref/bootstrap.php" 2>&1 26 | fi 27 | done 28 | -------------------------------------------------------------------------------- /layers/fpm-dev/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:1.4 2 | ARG CPU_PREFIX 3 | ARG PHP_VERSION 4 | 5 | 6 | FROM bref/${CPU_PREFIX}build-php-$PHP_VERSION as build_extensions 7 | 8 | ARG PHP_VERSION 9 | 10 | RUN mkdir -p /opt/bref/extensions 11 | 12 | # Install xdebug 13 | RUN pecl install xdebug-3.4.3 14 | RUN cp $(php -r "echo ini_get('extension_dir');")/xdebug.so /opt/bref/extensions 15 | 16 | # Install Blackfire 17 | # https://blackfire.io/docs/up-and-running/installation?action=install&mode=full&version=latest&mode=full&location=server&os=manual&language=php#install-the-php-probe 18 | ARG BLACKFIRE_VERSION=1.87.2 19 | RUN if [ $PHP_VERSION != "83" ] && [ $PHP_VERSION != "84" ] && [ $CPU_PREFIX == "" ]; then curl -A "Docker" -o /opt/bref/extensions/blackfire.so -L -s "https://packages.blackfire.io/binaries/blackfire-php/$BLACKFIRE_VERSION/blackfire-php-linux_amd64-php-"$PHP_VERSION".so"; fi 20 | RUN if [ $PHP_VERSION != "83" ] && [ $PHP_VERSION != "84" ] && [ $CPU_PREFIX == "arm-" ]; then curl -A "Docker" -o /opt/bref/extensions/blackfire.so -L -s "https://packages.blackfire.io/binaries/blackfire-php/$BLACKFIRE_VERSION/blackfire-php-linux_arm64-php-"$PHP_VERSION".so"; fi 21 | 22 | 23 | FROM bref/${CPU_PREFIX}php-${PHP_VERSION}-fpm 24 | 25 | COPY --link --from=build_extensions /opt /opt 26 | COPY --link bref-entrypoint.sh / 27 | RUN chmod +x /bref-entrypoint.sh 28 | 29 | # Install node to run the JS app below 30 | RUN yum install https://rpm.nodesource.com/pub_16.x/nodistro/repo/nodesource-release-nodistro-1.noarch.rpm -y 31 | RUN yum install --setopt=nodesource-nodejs.module_hotfixes=1 --setopt=skip_missing_names_on_install=False -y nodejs 32 | 33 | # Install the bref/local-api-gateway app in our container (avoids running 2 containers) 34 | COPY --link --from=bref/local-api-gateway /app /local-api-gateway 35 | EXPOSE 8000 36 | 37 | # Add `php/conf.dev.d` to the path where PHP looks for configuration files 38 | ENV PHP_INI_SCAN_DIR="/opt/bref/etc/php/conf.d:/var/task/php/conf.d:/var/task/php/conf.dev.d" 39 | 40 | # Add composer 41 | COPY --link --from=composer/composer:2-bin /composer /usr/bin/composer 42 | 43 | # Originally the entrypoint is `/lambda-entrypoint.sh` and CMD contains the handler name 44 | # We override the entrypoint to run our own logic 45 | ENTRYPOINT [ "/bref-entrypoint.sh" ] 46 | -------------------------------------------------------------------------------- /layers/fpm-dev/bref-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | # If a command is passed, run it (like "php artisan") 6 | if [ "$1" ]; 7 | then 8 | exec "$@" 9 | exit 0 10 | fi 11 | 12 | # Check that the $HANDLER variable is set 13 | if [ -z "$HANDLER" ]; 14 | then 15 | echo "The HANDLER environment variable is not set and no command was provided." 16 | echo "" 17 | echo "If you want to run the web server, set the of the Lambda handler in HANDLER," 18 | echo "for example 'index.php' or 'public/index.php'." 19 | echo "" 20 | echo "If you want to run a command, provide it as a Docker command." 21 | exit 1 22 | fi 23 | 24 | # Run the fake API Gateway 25 | # (forces fake AWS credentials so that the Lambda client works) 26 | # We point it to the local Lambda RIE and run in the background. 27 | # Yes, 2 processes in 1 container is bad. Guess what, I have flaws. 28 | # What are they? Oh, I don't know. I sing in the shower. Sometimes 29 | # I spend too much time volunteering. Occasionally I'll hit somebody 30 | # with my car. So sue me... No, don't sue me. That is the opposite 31 | # of the point that I'm trying to make. 32 | AWS_ACCESS_KEY_ID='fake' AWS_SECRET_ACCESS_KEY='fake' \ 33 | TARGET=localhost:8080 \ 34 | node /local-api-gateway/dist/index.js & 35 | 36 | # Run the original AWS Lambda entrypoint (RIE) with the handler argument 37 | /lambda-entrypoint.sh "$HANDLER" 38 | -------------------------------------------------------------------------------- /layers/fpm/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Fail on error 4 | set -e 5 | 6 | # check if the RUNTIME_CLASS is already set 7 | if [ -z "${RUNTIME_CLASS}" ]; then 8 | export RUNTIME_CLASS="Bref\FpmRuntime\Main" 9 | fi 10 | 11 | while true 12 | do 13 | if [ -z "${EXPERIMENTAL_AWS_LAMBDA_EXEC_WRAPPER}" ]; then 14 | # Default behavior 15 | 16 | # We redirect stderr to stdout so that everything 17 | # written on the output ends up in Cloudwatch automatically 18 | php "/opt/bref/bootstrap.php" 2>&1 19 | else 20 | # A wrapper script is configured 21 | # See https://docs.aws.amazon.com/lambda/latest/dg/runtimes-modify.html#runtime-wrapper 22 | # NOTE: EXPERIMENTAL FEATURE, DO NOT USE!!! 23 | # Note: If you do use it, open an issue or GitHub discussion or Slack thread 24 | # and let us know why it's useful to you, we might turn it into an official feature 25 | "${EXPERIMENTAL_AWS_LAMBDA_EXEC_WRAPPER}" php "/opt/bref/bootstrap.php" 2>&1 26 | fi 27 | done 28 | -------------------------------------------------------------------------------- /layers/fpm/bref.ini: -------------------------------------------------------------------------------- 1 | ; Do not display errors in production because with PHP-FPM that means 2 | ; errors will be output in the HTTP response 3 | display_errors=0 4 | 5 | ; Since PHP 7.4 the default value is E_ALL 6 | ; We override it to set the recommended configuration value for production. 7 | ; See https://github.com/php/php-src/blob/d91abf76e01a3c39424e8192ad049f473f900936/php.ini-production#L463 8 | error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT 9 | 10 | memory_limit=10240M 11 | 12 | opcache.enable=1 13 | 14 | ; Skip this check to save a bit 15 | opcache.validate_permission=0 16 | 17 | ; The code is readonly on lambdas so it never changes 18 | ; This setting is now disabled: code could be written to /tmp which is read/write 19 | ; (e.g. a compiled container) Such a performance optimization can be done by users. 20 | ;opcache.validate_timestamps=0 21 | 22 | ; Set sane values, modern PHP applications have higher needs than opcache's defaults 23 | ; See https://tideways.com/profiler/blog/fine-tune-your-opcache-configuration-to-avoid-caching-suprises 24 | opcache.memory_consumption=128 25 | opcache.max_accelerated_files=10000 26 | 27 | ; This directive determines which super global arrays are registered when PHP 28 | ; starts up. G,P,C,E & S are abbreviations for the following respective super 29 | ; globals: GET, POST, COOKIE, ENV and SERVER. 30 | ; We explicitly populate all variables else ENV is not populated by default. 31 | ; See https://github.com/brefphp/bref/pull/291 32 | variables_order="EGPCS" 33 | 34 | ; The lambda environment is not compatible with fastcgi_finish_request 35 | ; See https://github.com/brefphp/bref/issues/214 36 | disable_functions=fastcgi_finish_request 37 | 38 | ; API Gateway has a timeout of 29 seconds. Setting this to 28 will give PHP some 39 | ; time to properly finish up its resources and flush logs to CloudWatch. 40 | max_execution_time=28 41 | 42 | ; The total upload size limit is 6Mb, we override the defaults to match this limit 43 | ; API Gateway has a 10Mb limit, but Lambda's is 6Mb 44 | post_max_size=6M 45 | upload_max_filesize=6M 46 | 47 | extension_dir=/opt/bref/extensions 48 | ; Extensions enabled by default 49 | extension=pdo_mysql.so 50 | zend_extension=opcache.so 51 | -------------------------------------------------------------------------------- /layers/fpm/php-fpm.conf: -------------------------------------------------------------------------------- 1 | ; Logging anywhere on disk doesn't make sense on lambda since instances are ephemeral 2 | error_log = /dev/null 3 | pid = /tmp/.bref/php-fpm.pid 4 | ; Log above warning because PHP-FPM logs useless notices 5 | ; We must comment this flag else uncaught exceptions/fatal errors are not reported in the logs! 6 | ; TODO: report that to the PHP bug tracker 7 | ;log_level = 'warning' 8 | 9 | ; New PHP 7.3 option that includes the maximum length when writing to stderr 10 | log_limit = 8192 11 | 12 | [default] 13 | pm = static 14 | ; We only need one child because a lambda can process only one request at a time 15 | pm.max_children = 1 16 | listen = /tmp/.bref/php-fpm.sock 17 | ; Allows PHP processes to access the lambda's environment variables 18 | clear_env = no 19 | ; Forward stderr of PHP processes to stderr of PHP-FPM (so that it can be sent to cloudwatch) 20 | catch_workers_output = yes 21 | ; New PHP 7.3 option that disables a verbose log prefix 22 | decorate_workers_output = no 23 | ; Limit the number of core dump logs to 1 to avoid filling up the /tmp disk 24 | ; See https://github.com/brefphp/bref/issues/275 25 | rlimit_core = 1 26 | 27 | user = nobody 28 | -------------------------------------------------------------------------------- /layers/function/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Fail on error 4 | set -e 5 | 6 | # check if the RUNTIME_CLASS is already set 7 | if [ -z "${RUNTIME_CLASS}" ]; then 8 | export RUNTIME_CLASS="Bref\FunctionRuntime\Main" 9 | fi 10 | 11 | while true 12 | do 13 | if [ -z "${EXPERIMENTAL_AWS_LAMBDA_EXEC_WRAPPER}" ]; then 14 | # Default behavior 15 | 16 | # We redirect stderr to stdout so that everything 17 | # written on the output ends up in Cloudwatch automatically 18 | php "/opt/bref/bootstrap.php" 2>&1 19 | else 20 | # A wrapper script is configured 21 | # See https://docs.aws.amazon.com/lambda/latest/dg/runtimes-modify.html#runtime-wrapper 22 | # NOTE: EXPERIMENTAL FEATURE, DO NOT USE!!! 23 | # Note: If you do use it, open an issue or GitHub discussion or Slack thread 24 | # and let us know why it's useful to you, we might turn it into an official feature 25 | "${EXPERIMENTAL_AWS_LAMBDA_EXEC_WRAPPER}" php "/opt/bref/bootstrap.php" 2>&1 26 | fi 27 | done 28 | -------------------------------------------------------------------------------- /layers/function/bref.ini: -------------------------------------------------------------------------------- 1 | ; On the CLI we want errors to be sent to stdout -> those will end up in CloudWatch 2 | display_errors=1 3 | 4 | ; Since PHP 7.4 the default value is E_ALL 5 | ; We override it to set the recommended configuration value for production. 6 | ; See https://github.com/php/php-src/blob/d91abf76e01a3c39424e8192ad049f473f900936/php.ini-production#L463 7 | error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT 8 | 9 | memory_limit=10240M 10 | 11 | opcache.enable=1 12 | opcache.enable_cli=1 13 | 14 | ; Store the opcodes into a file cache instead of memory 15 | ; Since PHP runs on lambdas with a new process each time the memory cache is lost 16 | ; TODO store in a subdirectory (but the problem is that the subdirectory doesn't exist when PHP starts...) 17 | opcache.file_cache="/tmp" 18 | ; Disable the memory cache since it's useless 19 | ; In my tests it allows to gain 30% of response time in a classic API controller 20 | opcache.file_cache_only=1 21 | ; Skip this check to save a bit 22 | opcache.validate_permission=0 23 | 24 | ; The code is readonly on lambdas so it never changes 25 | ; This setting is now disabled: code could be written to /tmp which is read/write 26 | ; (e.g. a compiled container) Such a performance optimization can be done by users. 27 | ;opcache.validate_timestamps=0 28 | 29 | ; Set sane values, modern PHP applications have higher needs than opcache's defaults 30 | ; See https://tideways.com/profiler/blog/fine-tune-your-opcache-configuration-to-avoid-caching-suprises 31 | opcache.memory_consumption=128 32 | opcache.max_accelerated_files=10000 33 | 34 | ; This directive determines which super global arrays are registered when PHP 35 | ; starts up. G,P,C,E & S are abbreviations for the following respective super 36 | ; globals: GET, POST, COOKIE, ENV and SERVER. 37 | ; We explicitly populate all variables else ENV is not populated by default. 38 | ; See https://github.com/brefphp/bref/pull/291 39 | variables_order="EGPCS" 40 | 41 | extension_dir=/opt/bref/extensions 42 | ; Extensions enabled by default 43 | extension=pdo_mysql.so 44 | zend_extension=opcache.so 45 | -------------------------------------------------------------------------------- /output/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /php-80/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:1.4 2 | 3 | # Can be "x86_64" or "arm64" 4 | ARG IMAGE_VERSION_SUFFIX 5 | 6 | # https://www.php.net/downloads 7 | ARG VERSION_PHP=8.0.30 8 | 9 | 10 | # Lambda uses a custom AMI named Amazon Linux 2 11 | # https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html 12 | # AWS provides a Docker image that we use here: 13 | # https://github.com/amazonlinux/container-images/tree/amzn2 14 | FROM public.ecr.aws/lambda/provided:al2-${IMAGE_VERSION_SUFFIX} as build-environment 15 | 16 | 17 | RUN set -xe \ 18 | # Download yum repository data to cache 19 | && yum makecache \ 20 | # Install default development tools (gcc, make, etc) 21 | && yum groupinstall -y "Development Tools" --setopt=group_package_types=mandatory,default 22 | 23 | 24 | # The default version of cmake is 2.8.12. We need cmake to build a few of 25 | # our libraries, and at least one library requires a version of cmake greater than that. 26 | # Needed to build: 27 | # - libzip: minimum required CMAKE version 3.0. 28 | RUN LD_LIBRARY_PATH= yum install -y cmake3 29 | # Override the default `cmake` 30 | RUN ln -s /usr/bin/cmake3 /usr/bin/cmake 31 | 32 | 33 | # We need a base path for all the sourcecode we will build from. 34 | ENV BUILD_DIR="/tmp/build" 35 | 36 | # Target installation path for all the binaries and libraries we will compile. 37 | # We need to use /opt because that's where AWS Lambda layers are unzipped, 38 | # and we need binaries (e.g. /opt/bin/php) to look for libraries in /opt/lib. 39 | # Indeed, `/opt/lib` is a path Lambda looks for libraries by default (it is in `LD_LIBRARY_PATH`) 40 | # AND the `/opt/lib` path will be hardcoded in the compiled binaries and libraries (called "rpath"). 41 | # 42 | # Note: the /opt directory will be completely recreated from scratch in the final images, 43 | # so it's ok at this stage if we "pollute" it with plenty of extra libs/build artifacts. 44 | ENV INSTALL_DIR="/opt" 45 | 46 | # We need some default compiler variables setup 47 | ENV PKG_CONFIG_PATH="${INSTALL_DIR}/lib64/pkgconfig:${INSTALL_DIR}/lib/pkgconfig" \ 48 | PKG_CONFIG="/usr/bin/pkg-config" \ 49 | PATH="${INSTALL_DIR}/bin:${PATH}" 50 | 51 | ENV LD_LIBRARY_PATH="${INSTALL_DIR}/lib64:${INSTALL_DIR}/lib" 52 | 53 | # Enable parallelism by default for make and cmake (like make -j) 54 | # See https://stackoverflow.com/a/50883540/245552 55 | ENV CMAKE_BUILD_PARALLEL_LEVEL=4 56 | ENV MAKEFLAGS='-j4' 57 | 58 | # Ensure we have all the directories we require in the container. 59 | RUN mkdir -p ${BUILD_DIR} \ 60 | ${INSTALL_DIR}/bin \ 61 | ${INSTALL_DIR}/doc \ 62 | ${INSTALL_DIR}/etc/php \ 63 | ${INSTALL_DIR}/etc/php/conf.d \ 64 | ${INSTALL_DIR}/include \ 65 | ${INSTALL_DIR}/lib \ 66 | ${INSTALL_DIR}/lib64 \ 67 | ${INSTALL_DIR}/libexec \ 68 | ${INSTALL_DIR}/sbin \ 69 | ${INSTALL_DIR}/share 70 | 71 | 72 | ############################################################################### 73 | # ZLIB Build 74 | # We compile a newer version because Lambda uses an old version (1.2.7) that 75 | # has a security vulnerability (CVE-2022-37434). 76 | # See https://github.com/brefphp/aws-lambda-layers/pull/110 77 | # Can be removed once Lambda updates their version. 78 | # https://github.com/madler/zlib/releases 79 | ENV VERSION_ZLIB=1.3.1 80 | ENV ZLIB_BUILD_DIR=${BUILD_DIR}/zlib 81 | RUN set -xe; \ 82 | mkdir -p ${ZLIB_BUILD_DIR}; \ 83 | curl -Ls https://github.com/madler/zlib/releases/download/v${VERSION_ZLIB}/zlib-${VERSION_ZLIB}.tar.gz \ 84 | | tar xzC ${ZLIB_BUILD_DIR} --strip-components=1 85 | WORKDIR ${ZLIB_BUILD_DIR}/ 86 | RUN set -xe; \ 87 | make distclean \ 88 | && CFLAGS="" \ 89 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 90 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 91 | ./configure \ 92 | --prefix=${INSTALL_DIR} 93 | RUN set -xe; \ 94 | make install \ 95 | && rm ${INSTALL_DIR}/lib/libz.a 96 | 97 | 98 | ############################################################################### 99 | # OPENSSL 100 | # https://github.com/openssl/openssl/releases 101 | # Needs: 102 | # - zlib 103 | # Needed by: 104 | # - curl 105 | # - php 106 | ENV VERSION_OPENSSL=1.1.1w 107 | ENV OPENSSL_BUILD_DIR=${BUILD_DIR}/openssl 108 | ENV CA_BUNDLE_SOURCE="https://curl.se/ca/cacert.pem" 109 | ENV CA_BUNDLE="${INSTALL_DIR}/bref/ssl/cert.pem" 110 | RUN set -xe; \ 111 | mkdir -p ${OPENSSL_BUILD_DIR}; \ 112 | curl -Ls https://github.com/openssl/openssl/archive/OpenSSL_${VERSION_OPENSSL//./_}.tar.gz \ 113 | | tar xzC ${OPENSSL_BUILD_DIR} --strip-components=1 114 | WORKDIR ${OPENSSL_BUILD_DIR}/ 115 | RUN CFLAGS="" \ 116 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 117 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 118 | ./config \ 119 | --prefix=${INSTALL_DIR} \ 120 | --openssldir=${INSTALL_DIR}/bref/ssl \ 121 | --release \ 122 | enable-tls1_3 \ 123 | no-tests \ 124 | shared \ 125 | zlib 126 | # Explicitly compile make without parallelism because it fails if we use -jX (no error message) 127 | # I'm not 100% sure why, and I already lost 4 hours on this, but I found this: 128 | # https://github.com/openssl/openssl/issues/9931 129 | # https://stackoverflow.com/questions/28639207/why-cant-i-compile-openssl-with-multiple-threads-make-j3 130 | # Run `make install_sw install_ssldirs` instead of `make install` to skip installing man pages https://github.com/openssl/openssl/issues/8170 131 | RUN make -j1 install_sw install_ssldirs 132 | RUN mkdir -p ${INSTALL_DIR}/bref/ssl && curl -Lk -o ${CA_BUNDLE} ${CA_BUNDLE_SOURCE} 133 | 134 | 135 | ############################################################################### 136 | # LIBXML2 137 | # https://gitlab.gnome.org/GNOME/libxml2/-/releases 138 | # Uses: 139 | # - zlib 140 | # Needed by: 141 | # - php 142 | # - libnghttp2 143 | ENV VERSION_XML2=2.11.9 144 | ENV XML2_BUILD_DIR=${BUILD_DIR}/xml2 145 | RUN set -xe; \ 146 | mkdir -p ${XML2_BUILD_DIR}; \ 147 | curl -Ls https://download.gnome.org/sources/libxml2/${VERSION_XML2%.*}/libxml2-${VERSION_XML2}.tar.xz \ 148 | | tar xJC ${XML2_BUILD_DIR} --strip-components=1 149 | WORKDIR ${XML2_BUILD_DIR}/ 150 | RUN CFLAGS="" \ 151 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 152 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 153 | ./configure \ 154 | --prefix=${INSTALL_DIR} \ 155 | --with-sysroot=${INSTALL_DIR} \ 156 | --enable-shared \ 157 | --disable-static \ 158 | --with-html \ 159 | --with-history \ 160 | --enable-ipv6=no \ 161 | --with-icu \ 162 | --with-zlib \ 163 | --without-python 164 | RUN make install \ 165 | && cp xml2-config ${INSTALL_DIR}/bin/xml2-config 166 | 167 | 168 | ############################################################################### 169 | # LIBSSH2 170 | # https://github.com/libssh2/libssh2/releases 171 | # Needs: 172 | # - zlib 173 | # - OpenSSL 174 | # Needed by: 175 | # - curl 176 | ENV VERSION_LIBSSH2=1.11.1 177 | ENV LIBSSH2_BUILD_DIR=${BUILD_DIR}/libssh2 178 | RUN set -xe; \ 179 | mkdir -p ${LIBSSH2_BUILD_DIR}/bin; \ 180 | curl -Ls https://github.com/libssh2/libssh2/releases/download/libssh2-${VERSION_LIBSSH2}/libssh2-${VERSION_LIBSSH2}.tar.gz \ 181 | | tar xzC ${LIBSSH2_BUILD_DIR} --strip-components=1 182 | WORKDIR ${LIBSSH2_BUILD_DIR}/bin/ 183 | RUN CFLAGS="" \ 184 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 185 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 186 | cmake .. \ 187 | # Build as a shared library (.so) instead of a static one 188 | -DBUILD_SHARED_LIBS=ON \ 189 | # Build with OpenSSL support 190 | -DCRYPTO_BACKEND=OpenSSL \ 191 | # Build with zlib support 192 | -DENABLE_ZLIB_COMPRESSION=ON \ 193 | -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \ 194 | -DCMAKE_BUILD_TYPE=RELEASE 195 | RUN cmake --build . --target install 196 | 197 | 198 | ############################################################################### 199 | # LIBNGHTTP2 200 | # This adds support for HTTP 2 requests in curl. 201 | # See https://github.com/brefphp/bref/issues/727 and https://github.com/brefphp/bref/pull/740 202 | # https://github.com/nghttp2/nghttp2/releases 203 | # Needs: 204 | # - zlib 205 | # - OpenSSL 206 | # - libxml2 207 | # Needed by: 208 | # - curl 209 | ENV VERSION_NGHTTP2=1.65.0 210 | ENV NGHTTP2_BUILD_DIR=${BUILD_DIR}/nghttp2 211 | RUN set -xe; \ 212 | mkdir -p ${NGHTTP2_BUILD_DIR}; \ 213 | curl -Ls https://github.com/nghttp2/nghttp2/releases/download/v${VERSION_NGHTTP2}/nghttp2-${VERSION_NGHTTP2}.tar.gz \ 214 | | tar xzC ${NGHTTP2_BUILD_DIR} --strip-components=1 215 | WORKDIR ${NGHTTP2_BUILD_DIR}/ 216 | RUN CFLAGS="" \ 217 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 218 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 219 | ./configure \ 220 | --enable-lib-only \ 221 | --prefix=${INSTALL_DIR} 222 | RUN make install 223 | 224 | 225 | ############################################################################### 226 | # LIBPSL 227 | # This adds support for the public suffix list in curl. 228 | # https://github.com/rockdaboot/libpsl/releases 229 | # Needed by: 230 | # - curl 231 | ENV VERSION_LIBPSL=0.21.5 232 | ENV LIBPSL_BUILD_DIR=${BUILD_DIR}/libpsl 233 | RUN set -xe; \ 234 | mkdir -p ${LIBPSL_BUILD_DIR}; \ 235 | curl -Ls https://github.com/rockdaboot/libpsl/releases/download/${VERSION_LIBPSL}/libpsl-${VERSION_LIBPSL}.tar.gz \ 236 | | tar xzC ${LIBPSL_BUILD_DIR} --strip-components=1 237 | WORKDIR ${LIBPSL_BUILD_DIR}/ 238 | RUN CFLAGS="" \ 239 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 240 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 241 | ./configure \ 242 | --prefix=${INSTALL_DIR} 243 | RUN make -j $(nproc) && make install 244 | 245 | 246 | ############################################################################### 247 | # CURL 248 | # # https://github.com/curl/curl/releases 249 | # # Needs: 250 | # # - zlib 251 | # # - OpenSSL 252 | # # - libssh2 253 | # # - libnghttp2 254 | # # Needed by: 255 | # # - php 256 | ENV VERSION_CURL=8.14.1 257 | ENV CURL_BUILD_DIR=${BUILD_DIR}/curl 258 | RUN set -xe; \ 259 | mkdir -p ${CURL_BUILD_DIR}/bin; \ 260 | curl -Ls https://github.com/curl/curl/archive/curl-${VERSION_CURL//./_}.tar.gz \ 261 | | tar xzC ${CURL_BUILD_DIR} --strip-components=1 262 | WORKDIR ${CURL_BUILD_DIR}/ 263 | RUN ./buildconf \ 264 | && CFLAGS="" \ 265 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 266 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 267 | ./configure \ 268 | --prefix=${INSTALL_DIR} \ 269 | --with-ca-bundle=${CA_BUNDLE} \ 270 | --enable-shared \ 271 | --disable-static \ 272 | --enable-optimize \ 273 | --disable-warnings \ 274 | --disable-dependency-tracking \ 275 | --with-zlib \ 276 | --enable-http \ 277 | --enable-ftp \ 278 | --enable-file \ 279 | --enable-proxy \ 280 | --enable-tftp \ 281 | --enable-ipv6 \ 282 | --enable-openssl-auto-load-config \ 283 | --enable-cookies \ 284 | --with-gnu-ld \ 285 | --with-ssl \ 286 | --with-libssh2 \ 287 | --with-nghttp2 288 | RUN make install 289 | 290 | 291 | ############################################################################### 292 | # LIBZIP 293 | # https://github.com/nih-at/libzip/releases 294 | # Needed by: 295 | # - php 296 | ENV VERSION_ZIP=1.11.4 297 | ENV ZIP_BUILD_DIR=${BUILD_DIR}/zip 298 | RUN set -xe; \ 299 | mkdir -p ${ZIP_BUILD_DIR}/bin/; \ 300 | curl -Ls https://github.com/nih-at/libzip/releases/download/v${VERSION_ZIP}/libzip-${VERSION_ZIP}.tar.gz \ 301 | | tar xzC ${ZIP_BUILD_DIR} --strip-components=1 302 | WORKDIR ${ZIP_BUILD_DIR}/bin/ 303 | RUN CFLAGS="" \ 304 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 305 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 306 | cmake .. \ 307 | -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \ 308 | -DCMAKE_BUILD_TYPE=RELEASE 309 | RUN cmake --build . --target install 310 | 311 | 312 | ############################################################################### 313 | # LIBSODIUM 314 | # https://github.com/jedisct1/libsodium/releases 315 | # Needed by: 316 | # - php 317 | ENV VERSION_LIBSODIUM=1.0.20 318 | ENV LIBSODIUM_BUILD_DIR=${BUILD_DIR}/libsodium 319 | RUN set -xe; \ 320 | mkdir -p ${LIBSODIUM_BUILD_DIR}; \ 321 | curl -Ls https://github.com/jedisct1/libsodium/archive/${VERSION_LIBSODIUM}-RELEASE.tar.gz \ 322 | | tar xzC ${LIBSODIUM_BUILD_DIR} --strip-components=1 323 | WORKDIR ${LIBSODIUM_BUILD_DIR}/ 324 | RUN CFLAGS="" \ 325 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 326 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 327 | ./autogen.sh \ 328 | && ./configure --prefix=${INSTALL_DIR} 329 | RUN make install 330 | 331 | 332 | ############################################################################### 333 | # Postgres 334 | # https://github.com/postgres/postgres/tags 335 | # Needs: 336 | # - OpenSSL 337 | # Needed by: 338 | # - php 339 | ENV VERSION_POSTGRES=17.5 340 | ENV POSTGRES_BUILD_DIR=${BUILD_DIR}/postgres 341 | RUN set -xe; \ 342 | mkdir -p ${POSTGRES_BUILD_DIR}/bin; \ 343 | curl -Ls https://github.com/postgres/postgres/archive/REL_${VERSION_POSTGRES//./_}.tar.gz \ 344 | | tar xzC ${POSTGRES_BUILD_DIR} --strip-components=1 345 | WORKDIR ${POSTGRES_BUILD_DIR}/ 346 | RUN CFLAGS="" \ 347 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 348 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 349 | ./configure --prefix=${INSTALL_DIR} --with-openssl --without-icu --without-readline 350 | RUN cd ${POSTGRES_BUILD_DIR}/src/interfaces/libpq && make && make install 351 | RUN cd ${POSTGRES_BUILD_DIR}/src/bin/pg_config && make && make install 352 | RUN cd ${POSTGRES_BUILD_DIR}/src/backend && make generated-headers 353 | RUN cd ${POSTGRES_BUILD_DIR}/src/include && make install 354 | 355 | 356 | ############################################################################### 357 | # Oniguruma 358 | # This library is not packaged in PHP since PHP 7.4. 359 | # See https://github.com/php/php-src/blob/43dc7da8e3719d3e89bd8ec15ebb13f997bbbaa9/UPGRADING#L578-L581 360 | # We do not install the system version because I didn't manage to make it work... 361 | # Ideally we shouldn't compile it ourselves. 362 | # https://github.com/kkos/oniguruma/releases 363 | # Needed by: 364 | # - php mbstring 365 | ENV VERSION_ONIG=6.9.10 366 | ENV ONIG_BUILD_DIR=${BUILD_DIR}/oniguruma 367 | RUN set -xe; \ 368 | mkdir -p ${ONIG_BUILD_DIR}; \ 369 | curl -Ls https://github.com/kkos/oniguruma/releases/download/v${VERSION_ONIG}/onig-${VERSION_ONIG}.tar.gz \ 370 | | tar xzC ${ONIG_BUILD_DIR} --strip-components=1 371 | WORKDIR ${ONIG_BUILD_DIR} 372 | RUN ./configure --prefix=${INSTALL_DIR} 373 | RUN make && make install 374 | 375 | 376 | ############################################################################### 377 | # Install some dev files for using old libraries already on the system 378 | # readline-devel : needed for the readline extension 379 | # gettext-devel : needed for the --with-gettext flag 380 | # libicu-devel : needed for intl 381 | # libxslt-devel : needed for the XSL extension 382 | # sqlite-devel : Since PHP 7.4 this must be installed (https://github.com/php/php-src/blob/99b8e67615159fc600a615e1e97f2d1cf18f14cb/UPGRADING#L616-L619) 383 | # libffi-devel : needed for the FFI extension 384 | RUN LD_LIBRARY_PATH= yum install -y readline-devel gettext-devel libicu-devel libxslt-devel sqlite-devel libffi-devel 385 | 386 | # Note: this variable is used when building extra/custom extensions, do not remove 387 | ENV PHP_BUILD_DIR=/tmp/php 388 | 389 | # PHP Build 390 | # https://github.com/php/php-src/releases 391 | # Needs: 392 | # - zlib 393 | # - libxml2 394 | # - openssl 395 | # - readline 396 | # - sodium 397 | RUN mkdir -p ${PHP_BUILD_DIR} 398 | WORKDIR ${PHP_BUILD_DIR} 399 | 400 | # Download and unpack the source code 401 | # --location will follow redirects 402 | # --silent will hide the progress, but also the errors: we restore error messages with --show-error 403 | # --fail makes sure that curl returns an error instead of fetching the 404 page 404 | ARG VERSION_PHP 405 | RUN curl --location --silent --show-error --fail https://www.php.net/get/php-${VERSION_PHP}.tar.gz/from/this/mirror \ 406 | | tar xzC . --strip-components=1 407 | 408 | # Configure the build 409 | # -fstack-protector-strong : Be paranoid about stack overflows 410 | # -fpic : Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64) 411 | # -fpie : Support Address Space Layout Randomization (see -fpic) 412 | # -O3 : Optimize for fastest binaries possible. 413 | # -I : Add the path to the list of directories to be searched for header files during preprocessing. 414 | # --enable-option-checking=fatal: make sure invalid --configure-flags are fatal errors instead of just warnings 415 | # --enable-ftp: because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236) 416 | # --enable-mbstring: because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195) 417 | # --with-zlib and --with-zlib-dir: See https://stackoverflow.com/a/42978649/245552 418 | ARG PHP_COMPILATION_FLAGS 419 | RUN ./buildconf --force 420 | RUN CFLAGS="-fstack-protector-strong -fpic -fpie -O3 -I${INSTALL_DIR}/include -I/usr/include -ffunction-sections -fdata-sections" \ 421 | CPPFLAGS="-fstack-protector-strong -fpic -fpie -O3 -I${INSTALL_DIR}/include -I/usr/include -ffunction-sections -fdata-sections" \ 422 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib -Wl,-O1 -Wl,--strip-all -Wl,--hash-style=both -pie" \ 423 | ./configure \ 424 | --prefix=${INSTALL_DIR} \ 425 | --enable-option-checking=fatal \ 426 | --enable-sockets \ 427 | --with-config-file-path=/opt/bref/etc/php \ 428 | --with-config-file-scan-dir=/opt/bref/etc/php/conf.d:/var/task/php/conf.d \ 429 | --enable-fpm \ 430 | --disable-cgi \ 431 | --enable-cli \ 432 | --disable-phpdbg \ 433 | --with-sodium \ 434 | --with-readline \ 435 | --with-openssl \ 436 | --with-zlib \ 437 | --with-zlib-dir \ 438 | --with-curl \ 439 | --enable-exif \ 440 | --enable-ftp \ 441 | --with-gettext \ 442 | --enable-mbstring \ 443 | --with-pdo-mysql=shared,mysqlnd \ 444 | --with-mysqli \ 445 | --enable-pcntl \ 446 | --with-zip \ 447 | --enable-bcmath \ 448 | --with-pdo-pgsql=shared,${INSTALL_DIR} \ 449 | --enable-intl=shared \ 450 | --enable-soap \ 451 | --with-xsl=${INSTALL_DIR} \ 452 | --with-ffi \ 453 | # necessary for `pecl` to work (to install PHP extensions) 454 | --with-pear \ 455 | # extra compilation flags 456 | ${PHP_COMPILATION_FLAGS} 457 | RUN make -j $(nproc) 458 | # Run `make install` and override PEAR's PHAR URL because pear.php.net is down 459 | RUN set -xe; \ 460 | make install PEAR_INSTALLER_URL='https://github.com/pear/pearweb_phars/raw/master/install-pear-nozlib.phar'; \ 461 | { find ${INSTALL_DIR}/bin ${INSTALL_DIR}/sbin -type f -perm +0111 -exec strip --strip-all '{}' + || true; }; \ 462 | make clean; \ 463 | cp php.ini-production ${INSTALL_DIR}/etc/php/php.ini 464 | 465 | 466 | # Install extensions 467 | # We can install extensions manually or using `pecl` 468 | ENV VERSION_APCU=5.1.24 469 | RUN pecl install apcu-${VERSION_APCU} 470 | 471 | 472 | # --------------------------------------------------------------- 473 | # Now we copy everything we need for the layers into /bref-layer (which will be used for the real /opt later) 474 | RUN mkdir -p /bref-layer/bin \ 475 | && mkdir -p /bref-layer/lib \ 476 | && mkdir -p /bref-layer/bref/extensions \ 477 | && mkdir -p /bref-layer/bref/ssl 478 | 479 | # Copy the PHP binary 480 | RUN cp ${INSTALL_DIR}/bin/php /bref-layer/bin/php && chmod +x /bref-layer/bin/php 481 | 482 | # Copy all the external PHP extensions 483 | RUN cp $(php -r 'echo ini_get("extension_dir");')/* /bref-layer/bref/extensions/ 484 | 485 | # Copy all the required system libraries from: 486 | # - /lib | /lib64 (system libraries installed with `yum`) 487 | # - /opt/bin | /opt/lib | /opt/lib64 (libraries compiled from source) 488 | # into `/bref-layer` (the temp directory for the future Lambda layer) 489 | COPY --link utils/lib-copy /bref/lib-copy 490 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bin/php /bref-layer/lib 491 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/apcu.so /bref-layer/lib 492 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/intl.so /bref-layer/lib 493 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/opcache.so /bref-layer/lib 494 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/pdo_mysql.so /bref-layer/lib 495 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/pdo_pgsql.so /bref-layer/lib 496 | 497 | # Copy the OpenSSL certificates file 498 | RUN cp ${CA_BUNDLE} /bref-layer/bref/ssl/cert.pem 499 | 500 | # Copy the OpenSSL config 501 | RUN cp ${INSTALL_DIR}/bref/ssl/openssl.cnf /bref-layer/bref/ssl/openssl.cnf 502 | 503 | 504 | # --------------------------------------------------------------- 505 | # Start from a clean image to copy only the files we need 506 | FROM public.ecr.aws/lambda/provided:al2-${IMAGE_VERSION_SUFFIX} as isolation 507 | 508 | # We selected the files in /bref-layer, now we copy them to /opt (the real directory for the Lambda layer) 509 | COPY --link --from=build-environment /bref-layer /opt 510 | 511 | COPY --link layers/bootstrap.php /opt/bref/bootstrap.php 512 | 513 | 514 | FROM isolation as function 515 | 516 | COPY --link layers/function/bref.ini /opt/bref/etc/php/conf.d/ 517 | 518 | COPY --link layers/function/bootstrap.sh /opt/bootstrap 519 | # Copy files to /var/runtime to support deploying as a Docker image 520 | COPY --link layers/function/bootstrap.sh /var/runtime/bootstrap 521 | RUN chmod +x /opt/bootstrap && chmod +x /var/runtime/bootstrap 522 | 523 | 524 | # Up until here the entire file has been designed as a top-down reading/execution. 525 | # Everything necessary for the `function` layer has been installed, isolated and 526 | # packaged. Now we'll go back one step and start from the extensions so that we 527 | # can install fpm. Then we'll start the fpm layer and quickly isolate fpm. 528 | 529 | FROM build-environment as fpm-extension 530 | 531 | RUN cp ${INSTALL_DIR}/sbin/php-fpm /bref-layer/bin/php-fpm 532 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bin/php-fpm /bref-layer/lib 533 | 534 | 535 | FROM isolation as fpm 536 | 537 | COPY --link --from=fpm-extension /bref-layer /opt 538 | 539 | COPY --link layers/fpm/bref.ini /opt/bref/etc/php/conf.d/ 540 | 541 | COPY --link layers/fpm/bootstrap.sh /opt/bootstrap 542 | # Copy files to /var/runtime to support deploying as a Docker image 543 | COPY --link layers/fpm/bootstrap.sh /var/runtime/bootstrap 544 | RUN chmod +x /opt/bootstrap && chmod +x /var/runtime/bootstrap 545 | 546 | COPY --link layers/fpm/php-fpm.conf /opt/bref/etc/php-fpm.conf 547 | -------------------------------------------------------------------------------- /php-81/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:1.4 2 | 3 | # Can be "x86_64" or "arm64" 4 | ARG IMAGE_VERSION_SUFFIX 5 | 6 | # https://www.php.net/downloads 7 | ARG VERSION_PHP=8.1.32 8 | 9 | 10 | # Lambda uses a custom AMI named Amazon Linux 2 11 | # https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html 12 | # AWS provides a Docker image that we use here: 13 | # https://github.com/amazonlinux/container-images/tree/amzn2 14 | FROM public.ecr.aws/lambda/provided:al2-${IMAGE_VERSION_SUFFIX} as build-environment 15 | 16 | 17 | RUN set -xe \ 18 | # Download yum repository data to cache 19 | && yum makecache \ 20 | # Install default development tools (gcc, make, etc) 21 | && yum groupinstall -y "Development Tools" --setopt=group_package_types=mandatory,default 22 | 23 | 24 | # The default version of cmake is 2.8.12. We need cmake to build a few of 25 | # our libraries, and at least one library requires a version of cmake greater than that. 26 | # Needed to build: 27 | # - libzip: minimum required CMAKE version 3.0. 28 | RUN LD_LIBRARY_PATH= yum install -y cmake3 29 | # Override the default `cmake` 30 | RUN ln -s /usr/bin/cmake3 /usr/bin/cmake 31 | 32 | 33 | # We need a base path for all the sourcecode we will build from. 34 | ENV BUILD_DIR="/tmp/build" 35 | 36 | # Target installation path for all the binaries and libraries we will compile. 37 | # We need to use /opt because that's where AWS Lambda layers are unzipped, 38 | # and we need binaries (e.g. /opt/bin/php) to look for libraries in /opt/lib. 39 | # Indeed, `/opt/lib` is a path Lambda looks for libraries by default (it is in `LD_LIBRARY_PATH`) 40 | # AND the `/opt/lib` path will be hardcoded in the compiled binaries and libraries (called "rpath"). 41 | # 42 | # Note: the /opt directory will be completely recreated from scratch in the final images, 43 | # so it's ok at this stage if we "pollute" it with plenty of extra libs/build artifacts. 44 | ENV INSTALL_DIR="/opt" 45 | 46 | # We need some default compiler variables setup 47 | ENV PKG_CONFIG_PATH="${INSTALL_DIR}/lib64/pkgconfig:${INSTALL_DIR}/lib/pkgconfig" \ 48 | PKG_CONFIG="/usr/bin/pkg-config" \ 49 | PATH="${INSTALL_DIR}/bin:${PATH}" 50 | 51 | ENV LD_LIBRARY_PATH="${INSTALL_DIR}/lib64:${INSTALL_DIR}/lib" 52 | 53 | # Enable parallelism by default for make and cmake (like make -j) 54 | # See https://stackoverflow.com/a/50883540/245552 55 | ENV CMAKE_BUILD_PARALLEL_LEVEL=4 56 | ENV MAKEFLAGS='-j4' 57 | 58 | # Ensure we have all the directories we require in the container. 59 | RUN mkdir -p ${BUILD_DIR} \ 60 | ${INSTALL_DIR}/bin \ 61 | ${INSTALL_DIR}/doc \ 62 | ${INSTALL_DIR}/etc/php \ 63 | ${INSTALL_DIR}/etc/php/conf.d \ 64 | ${INSTALL_DIR}/include \ 65 | ${INSTALL_DIR}/lib \ 66 | ${INSTALL_DIR}/lib64 \ 67 | ${INSTALL_DIR}/libexec \ 68 | ${INSTALL_DIR}/sbin \ 69 | ${INSTALL_DIR}/share 70 | 71 | 72 | ############################################################################### 73 | # ZLIB Build 74 | # We compile a newer version because Lambda uses an old version (1.2.7) that 75 | # has a security vulnerability (CVE-2022-37434). 76 | # See https://github.com/brefphp/aws-lambda-layers/pull/110 77 | # Can be removed once Lambda updates their version. 78 | # https://github.com/madler/zlib/releases 79 | ENV VERSION_ZLIB=1.3.1 80 | ENV ZLIB_BUILD_DIR=${BUILD_DIR}/zlib 81 | RUN set -xe; \ 82 | mkdir -p ${ZLIB_BUILD_DIR}; \ 83 | curl -Ls https://github.com/madler/zlib/releases/download/v${VERSION_ZLIB}/zlib-${VERSION_ZLIB}.tar.gz \ 84 | | tar xzC ${ZLIB_BUILD_DIR} --strip-components=1 85 | WORKDIR ${ZLIB_BUILD_DIR}/ 86 | RUN set -xe; \ 87 | make distclean \ 88 | && CFLAGS="" \ 89 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 90 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 91 | ./configure \ 92 | --prefix=${INSTALL_DIR} 93 | RUN set -xe; \ 94 | make install \ 95 | && rm ${INSTALL_DIR}/lib/libz.a 96 | 97 | 98 | ############################################################################### 99 | # OPENSSL 100 | # https://github.com/openssl/openssl/releases 101 | # Needs: 102 | # - zlib 103 | # Needed by: 104 | # - curl 105 | # - php 106 | RUN yum install -y perl-IPC-Cmd 107 | ENV VERSION_OPENSSL=3.3.3 108 | ENV OPENSSL_BUILD_DIR=${BUILD_DIR}/openssl 109 | ENV CA_BUNDLE_SOURCE="https://curl.se/ca/cacert.pem" 110 | ENV CA_BUNDLE="${INSTALL_DIR}/bref/ssl/cert.pem" 111 | RUN set -xe; \ 112 | mkdir -p ${OPENSSL_BUILD_DIR}; \ 113 | curl -Ls https://github.com/openssl/openssl/releases/download/openssl-${VERSION_OPENSSL}/openssl-${VERSION_OPENSSL}.tar.gz \ 114 | | tar xzC ${OPENSSL_BUILD_DIR} --strip-components=1 115 | WORKDIR ${OPENSSL_BUILD_DIR}/ 116 | RUN CFLAGS="" \ 117 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 118 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 119 | ./config \ 120 | --prefix=${INSTALL_DIR} \ 121 | --openssldir=${INSTALL_DIR}/bref/ssl \ 122 | --release \ 123 | enable-tls1_3 \ 124 | no-tests \ 125 | shared \ 126 | zlib 127 | # Explicitly compile make without parallelism because it fails if we use -jX (no error message) 128 | # I'm not 100% sure why, and I already lost 4 hours on this, but I found this: 129 | # https://github.com/openssl/openssl/issues/9931 130 | # https://stackoverflow.com/questions/28639207/why-cant-i-compile-openssl-with-multiple-threads-make-j3 131 | # Run `make install_sw install_ssldirs` instead of `make install` to skip installing man pages https://github.com/openssl/openssl/issues/8170 132 | RUN make -j1 install_sw install_ssldirs 133 | RUN mkdir -p ${INSTALL_DIR}/bref/ssl && curl -Lk -o ${CA_BUNDLE} ${CA_BUNDLE_SOURCE} 134 | 135 | 136 | ############################################################################### 137 | # LIBXML2 138 | # https://gitlab.gnome.org/GNOME/libxml2/-/releases 139 | # Uses: 140 | # - zlib 141 | # Needed by: 142 | # - php 143 | # - libnghttp2 144 | ENV VERSION_XML2=2.12.10 145 | ENV XML2_BUILD_DIR=${BUILD_DIR}/xml2 146 | RUN set -xe; \ 147 | mkdir -p ${XML2_BUILD_DIR}; \ 148 | curl -Ls https://download.gnome.org/sources/libxml2/${VERSION_XML2%.*}/libxml2-${VERSION_XML2}.tar.xz \ 149 | | tar xJC ${XML2_BUILD_DIR} --strip-components=1 150 | WORKDIR ${XML2_BUILD_DIR}/ 151 | RUN CFLAGS="" \ 152 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 153 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 154 | ./configure \ 155 | --prefix=${INSTALL_DIR} \ 156 | --with-sysroot=${INSTALL_DIR} \ 157 | --enable-shared \ 158 | --disable-static \ 159 | --with-html \ 160 | --with-history \ 161 | --enable-ipv6=no \ 162 | --with-icu \ 163 | --with-zlib \ 164 | --without-python 165 | RUN make install \ 166 | && cp xml2-config ${INSTALL_DIR}/bin/xml2-config 167 | 168 | 169 | ############################################################################### 170 | # LIBSSH2 171 | # https://github.com/libssh2/libssh2/releases 172 | # Needs: 173 | # - zlib 174 | # - OpenSSL 175 | # Needed by: 176 | # - curl 177 | ENV VERSION_LIBSSH2=1.11.1 178 | ENV LIBSSH2_BUILD_DIR=${BUILD_DIR}/libssh2 179 | RUN set -xe; \ 180 | mkdir -p ${LIBSSH2_BUILD_DIR}/bin; \ 181 | curl -Ls https://github.com/libssh2/libssh2/releases/download/libssh2-${VERSION_LIBSSH2}/libssh2-${VERSION_LIBSSH2}.tar.gz \ 182 | | tar xzC ${LIBSSH2_BUILD_DIR} --strip-components=1 183 | WORKDIR ${LIBSSH2_BUILD_DIR}/bin/ 184 | RUN CFLAGS="" \ 185 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 186 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 187 | cmake .. \ 188 | # Build as a shared library (.so) instead of a static one 189 | -DBUILD_SHARED_LIBS=ON \ 190 | # Build with OpenSSL support 191 | -DCRYPTO_BACKEND=OpenSSL \ 192 | # Build with zlib support 193 | -DENABLE_ZLIB_COMPRESSION=ON \ 194 | -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \ 195 | -DCMAKE_BUILD_TYPE=RELEASE 196 | RUN cmake --build . --target install 197 | 198 | 199 | ############################################################################### 200 | # LIBNGHTTP2 201 | # This adds support for HTTP 2 requests in curl. 202 | # See https://github.com/brefphp/bref/issues/727 and https://github.com/brefphp/bref/pull/740 203 | # https://github.com/nghttp2/nghttp2/releases 204 | # Needs: 205 | # - zlib 206 | # - OpenSSL 207 | # - libxml2 208 | # Needed by: 209 | # - curl 210 | ENV VERSION_NGHTTP2=1.65.0 211 | ENV NGHTTP2_BUILD_DIR=${BUILD_DIR}/nghttp2 212 | RUN set -xe; \ 213 | mkdir -p ${NGHTTP2_BUILD_DIR}; \ 214 | curl -Ls https://github.com/nghttp2/nghttp2/releases/download/v${VERSION_NGHTTP2}/nghttp2-${VERSION_NGHTTP2}.tar.gz \ 215 | | tar xzC ${NGHTTP2_BUILD_DIR} --strip-components=1 216 | WORKDIR ${NGHTTP2_BUILD_DIR}/ 217 | RUN CFLAGS="" \ 218 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 219 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 220 | ./configure \ 221 | --enable-lib-only \ 222 | --prefix=${INSTALL_DIR} 223 | RUN make install 224 | 225 | 226 | ############################################################################### 227 | # LIBPSL 228 | # This adds support for the public suffix list in curl. 229 | # https://github.com/rockdaboot/libpsl/releases 230 | # Needed by: 231 | # - curl 232 | ENV VERSION_LIBPSL=0.21.5 233 | ENV LIBPSL_BUILD_DIR=${BUILD_DIR}/libpsl 234 | RUN set -xe; \ 235 | mkdir -p ${LIBPSL_BUILD_DIR}; \ 236 | curl -Ls https://github.com/rockdaboot/libpsl/releases/download/${VERSION_LIBPSL}/libpsl-${VERSION_LIBPSL}.tar.gz \ 237 | | tar xzC ${LIBPSL_BUILD_DIR} --strip-components=1 238 | WORKDIR ${LIBPSL_BUILD_DIR}/ 239 | RUN CFLAGS="" \ 240 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 241 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 242 | ./configure \ 243 | --prefix=${INSTALL_DIR} 244 | RUN make -j $(nproc) && make install 245 | 246 | 247 | ############################################################################### 248 | # CURL 249 | # # https://github.com/curl/curl/releases 250 | # # Needs: 251 | # # - zlib 252 | # # - OpenSSL 253 | # # - libssh2 254 | # # - libnghttp2 255 | # # Needed by: 256 | # # - php 257 | ENV VERSION_CURL=8.14.1 258 | ENV CURL_BUILD_DIR=${BUILD_DIR}/curl 259 | RUN set -xe; \ 260 | mkdir -p ${CURL_BUILD_DIR}/bin; \ 261 | curl -Ls https://github.com/curl/curl/archive/curl-${VERSION_CURL//./_}.tar.gz \ 262 | | tar xzC ${CURL_BUILD_DIR} --strip-components=1 263 | WORKDIR ${CURL_BUILD_DIR}/ 264 | RUN ./buildconf \ 265 | && CFLAGS="" \ 266 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 267 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 268 | ./configure \ 269 | --prefix=${INSTALL_DIR} \ 270 | --with-ca-bundle=${CA_BUNDLE} \ 271 | --enable-shared \ 272 | --disable-static \ 273 | --enable-optimize \ 274 | --disable-warnings \ 275 | --disable-dependency-tracking \ 276 | --with-zlib \ 277 | --enable-http \ 278 | --enable-ftp \ 279 | --enable-file \ 280 | --enable-proxy \ 281 | --enable-tftp \ 282 | --enable-ipv6 \ 283 | --enable-openssl-auto-load-config \ 284 | --enable-cookies \ 285 | --with-gnu-ld \ 286 | --with-ssl \ 287 | --with-libssh2 \ 288 | --with-nghttp2 289 | RUN make install 290 | 291 | 292 | ############################################################################### 293 | # LIBZIP 294 | # https://github.com/nih-at/libzip/releases 295 | # Needed by: 296 | # - php 297 | ENV VERSION_ZIP=1.11.4 298 | ENV ZIP_BUILD_DIR=${BUILD_DIR}/zip 299 | RUN set -xe; \ 300 | mkdir -p ${ZIP_BUILD_DIR}/bin/; \ 301 | curl -Ls https://github.com/nih-at/libzip/releases/download/v${VERSION_ZIP}/libzip-${VERSION_ZIP}.tar.gz \ 302 | | tar xzC ${ZIP_BUILD_DIR} --strip-components=1 303 | WORKDIR ${ZIP_BUILD_DIR}/bin/ 304 | RUN CFLAGS="" \ 305 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 306 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 307 | cmake .. \ 308 | -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \ 309 | -DCMAKE_BUILD_TYPE=RELEASE 310 | RUN cmake --build . --target install 311 | 312 | 313 | ############################################################################### 314 | # LIBSODIUM 315 | # https://github.com/jedisct1/libsodium/releases 316 | # Needed by: 317 | # - php 318 | ENV VERSION_LIBSODIUM=1.0.20 319 | ENV LIBSODIUM_BUILD_DIR=${BUILD_DIR}/libsodium 320 | RUN set -xe; \ 321 | mkdir -p ${LIBSODIUM_BUILD_DIR}; \ 322 | curl -Ls https://github.com/jedisct1/libsodium/archive/${VERSION_LIBSODIUM}-RELEASE.tar.gz \ 323 | | tar xzC ${LIBSODIUM_BUILD_DIR} --strip-components=1 324 | WORKDIR ${LIBSODIUM_BUILD_DIR}/ 325 | RUN CFLAGS="" \ 326 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 327 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 328 | ./autogen.sh \ 329 | && ./configure --prefix=${INSTALL_DIR} 330 | RUN make install 331 | 332 | 333 | ############################################################################### 334 | # Postgres 335 | # https://github.com/postgres/postgres/tags 336 | # Needs: 337 | # - OpenSSL 338 | # Needed by: 339 | # - php 340 | ENV VERSION_POSTGRES=17.5 341 | ENV POSTGRES_BUILD_DIR=${BUILD_DIR}/postgres 342 | RUN set -xe; \ 343 | mkdir -p ${POSTGRES_BUILD_DIR}/bin; \ 344 | curl -Ls https://github.com/postgres/postgres/archive/REL_${VERSION_POSTGRES//./_}.tar.gz \ 345 | | tar xzC ${POSTGRES_BUILD_DIR} --strip-components=1 346 | WORKDIR ${POSTGRES_BUILD_DIR}/ 347 | RUN CFLAGS="" \ 348 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 349 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 350 | ./configure --prefix=${INSTALL_DIR} --with-openssl --without-icu --without-readline 351 | RUN cd ${POSTGRES_BUILD_DIR}/src/interfaces/libpq && make && make install 352 | RUN cd ${POSTGRES_BUILD_DIR}/src/bin/pg_config && make && make install 353 | RUN cd ${POSTGRES_BUILD_DIR}/src/backend && make generated-headers 354 | RUN cd ${POSTGRES_BUILD_DIR}/src/include && make install 355 | 356 | 357 | ############################################################################### 358 | # Oniguruma 359 | # This library is not packaged in PHP since PHP 7.4. 360 | # See https://github.com/php/php-src/blob/43dc7da8e3719d3e89bd8ec15ebb13f997bbbaa9/UPGRADING#L578-L581 361 | # We do not install the system version because I didn't manage to make it work... 362 | # Ideally we shouldn't compile it ourselves. 363 | # https://github.com/kkos/oniguruma/releases 364 | # Needed by: 365 | # - php mbstring 366 | ENV VERSION_ONIG=6.9.10 367 | ENV ONIG_BUILD_DIR=${BUILD_DIR}/oniguruma 368 | RUN set -xe; \ 369 | mkdir -p ${ONIG_BUILD_DIR}; \ 370 | curl -Ls https://github.com/kkos/oniguruma/releases/download/v${VERSION_ONIG}/onig-${VERSION_ONIG}.tar.gz \ 371 | | tar xzC ${ONIG_BUILD_DIR} --strip-components=1 372 | WORKDIR ${ONIG_BUILD_DIR} 373 | RUN ./configure --prefix=${INSTALL_DIR} 374 | RUN make && make install 375 | 376 | 377 | ############################################################################### 378 | # SQLite 379 | # Since PHP 7.4, libsqlite must be installed (https://github.com/php/php-src/blob/99b8e67615159fc600a615e1e97f2d1cf18f14cb/UPGRADING#L616-L619) 380 | # Laravel 11 requires SQLite 3.35.0 or higher and Drupal 10 also requires a 381 | # newer version than the system version of 3.7.17. 382 | # https://laravel.com/docs/11.x/upgrade#sqlite-minimum-version 383 | # https://www.sqlite.org/changes.html 384 | # Needed by: 385 | # - php 386 | RUN LD_LIBRARY_PATH= yum install -y tcl 387 | ENV VERSION_SQLITE=3.50.0 388 | ENV SQLITE_BUILD_DIR=${BUILD_DIR}/sqlite 389 | RUN set -xe; \ 390 | mkdir -p ${SQLITE_BUILD_DIR}; \ 391 | curl -Ls https://github.com/sqlite/sqlite/archive/refs/tags/version-${VERSION_SQLITE}.tar.gz \ 392 | | tar xzC ${SQLITE_BUILD_DIR} --strip-components=1 393 | WORKDIR ${SQLITE_BUILD_DIR} 394 | RUN ./configure --prefix=${INSTALL_DIR} 395 | RUN make && make install 396 | 397 | 398 | ############################################################################### 399 | # Install some dev files for using old libraries already on the system 400 | # readline-devel : needed for the readline extension 401 | # gettext-devel : needed for the --with-gettext flag 402 | # libicu-devel : needed for intl 403 | # libxslt-devel : needed for the XSL extension 404 | # libffi-devel : needed for the FFI extension 405 | RUN LD_LIBRARY_PATH= yum install -y readline-devel gettext-devel libicu-devel libxslt-devel libffi-devel 406 | 407 | 408 | # Note: this variable is used when building extra/custom extensions, do not remove 409 | ENV PHP_BUILD_DIR=/tmp/php 410 | 411 | # PHP Build 412 | # https://github.com/php/php-src/releases 413 | # Needs: 414 | # - zlib 415 | # - libxml2 416 | # - openssl 417 | # - readline 418 | # - sodium 419 | RUN mkdir -p ${PHP_BUILD_DIR} 420 | WORKDIR ${PHP_BUILD_DIR} 421 | 422 | # Download and unpack the source code 423 | # --location will follow redirects 424 | # --silent will hide the progress, but also the errors: we restore error messages with --show-error 425 | # --fail makes sure that curl returns an error instead of fetching the 404 page 426 | ARG VERSION_PHP 427 | RUN curl --location --silent --show-error --fail https://www.php.net/get/php-${VERSION_PHP}.tar.gz/from/this/mirror \ 428 | | tar xzC . --strip-components=1 429 | 430 | # Configure the build 431 | # -fstack-protector-strong : Be paranoid about stack overflows 432 | # -fpic : Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64) 433 | # -fpie : Support Address Space Layout Randomization (see -fpic) 434 | # -O3 : Optimize for fastest binaries possible. 435 | # -I : Add the path to the list of directories to be searched for header files during preprocessing. 436 | # --enable-option-checking=fatal: make sure invalid --configure-flags are fatal errors instead of just warnings 437 | # --enable-ftp: because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236) 438 | # --enable-mbstring: because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195) 439 | # --with-zlib and --with-zlib-dir: See https://stackoverflow.com/a/42978649/245552 440 | ARG PHP_COMPILATION_FLAGS 441 | RUN ./buildconf --force 442 | RUN CFLAGS="-fstack-protector-strong -fpic -fpie -O3 -I${INSTALL_DIR}/include -I/usr/include -ffunction-sections -fdata-sections" \ 443 | CPPFLAGS="-fstack-protector-strong -fpic -fpie -O3 -I${INSTALL_DIR}/include -I/usr/include -ffunction-sections -fdata-sections" \ 444 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib -Wl,-O1 -Wl,--strip-all -Wl,--hash-style=both -pie" \ 445 | ./configure \ 446 | --prefix=${INSTALL_DIR} \ 447 | --enable-option-checking=fatal \ 448 | --enable-sockets \ 449 | --with-config-file-path=/opt/bref/etc/php \ 450 | --with-config-file-scan-dir=/opt/bref/etc/php/conf.d:/var/task/php/conf.d \ 451 | --enable-fpm \ 452 | --disable-cgi \ 453 | --enable-cli \ 454 | --disable-phpdbg \ 455 | --with-sodium \ 456 | --with-readline \ 457 | --with-openssl \ 458 | --with-zlib \ 459 | --with-zlib-dir \ 460 | --with-curl \ 461 | --enable-exif \ 462 | --enable-ftp \ 463 | --with-gettext \ 464 | --enable-mbstring \ 465 | --with-pdo-mysql=shared,mysqlnd \ 466 | --with-mysqli \ 467 | --enable-pcntl \ 468 | --with-zip \ 469 | --enable-bcmath \ 470 | --with-pdo-pgsql=shared,${INSTALL_DIR} \ 471 | --enable-intl=shared \ 472 | --enable-soap \ 473 | --with-xsl=${INSTALL_DIR} \ 474 | --with-ffi \ 475 | # necessary for `pecl` to work (to install PHP extensions) 476 | --with-pear \ 477 | # extra compilation flags 478 | ${PHP_COMPILATION_FLAGS} 479 | RUN make -j $(nproc) 480 | # Run `make install` and override PEAR's PHAR URL because pear.php.net is down 481 | RUN set -xe; \ 482 | make install PEAR_INSTALLER_URL='https://github.com/pear/pearweb_phars/raw/master/install-pear-nozlib.phar'; \ 483 | { find ${INSTALL_DIR}/bin ${INSTALL_DIR}/sbin -type f -perm +0111 -exec strip --strip-all '{}' + || true; }; \ 484 | make clean; \ 485 | cp php.ini-production ${INSTALL_DIR}/etc/php/php.ini 486 | 487 | 488 | # Install extensions 489 | # We can install extensions manually or using `pecl` 490 | ENV VERSION_APCU=5.1.24 491 | RUN pecl install apcu-${VERSION_APCU} 492 | 493 | 494 | # --------------------------------------------------------------- 495 | # Now we copy everything we need for the layers into /bref-layer (which will be used for the real /opt later) 496 | RUN mkdir -p /bref-layer/bin \ 497 | && mkdir -p /bref-layer/lib \ 498 | && mkdir -p /bref-layer/bref/extensions \ 499 | && mkdir -p /bref-layer/bref/ssl 500 | 501 | # Copy the PHP binary 502 | RUN cp ${INSTALL_DIR}/bin/php /bref-layer/bin/php && chmod +x /bref-layer/bin/php 503 | 504 | # Copy all the external PHP extensions 505 | RUN cp $(php -r 'echo ini_get("extension_dir");')/* /bref-layer/bref/extensions/ 506 | 507 | # Copy all the required system libraries from: 508 | # - /lib | /lib64 (system libraries installed with `yum`) 509 | # - /opt/bin | /opt/lib | /opt/lib64 (libraries compiled from source) 510 | # into `/bref-layer` (the temp directory for the future Lambda layer) 511 | COPY --link utils/lib-copy /bref/lib-copy 512 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bin/php /bref-layer/lib 513 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/apcu.so /bref-layer/lib 514 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/intl.so /bref-layer/lib 515 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/opcache.so /bref-layer/lib 516 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/pdo_mysql.so /bref-layer/lib 517 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/pdo_pgsql.so /bref-layer/lib 518 | 519 | # Copy the OpenSSL certificates file 520 | RUN cp ${CA_BUNDLE} /bref-layer/bref/ssl/cert.pem 521 | 522 | # Copy the OpenSSL config 523 | RUN cp ${INSTALL_DIR}/bref/ssl/openssl.cnf /bref-layer/bref/ssl/openssl.cnf 524 | 525 | 526 | # --------------------------------------------------------------- 527 | # Start from a clean image to copy only the files we need 528 | FROM public.ecr.aws/lambda/provided:al2-${IMAGE_VERSION_SUFFIX} as isolation 529 | 530 | # We selected the files in /bref-layer, now we copy them to /opt (the real directory for the Lambda layer) 531 | COPY --link --from=build-environment /bref-layer /opt 532 | 533 | COPY --link layers/bootstrap.php /opt/bref/bootstrap.php 534 | 535 | 536 | FROM isolation as function 537 | 538 | COPY --link layers/function/bref.ini /opt/bref/etc/php/conf.d/ 539 | 540 | COPY --link layers/function/bootstrap.sh /opt/bootstrap 541 | # Copy files to /var/runtime to support deploying as a Docker image 542 | COPY --link layers/function/bootstrap.sh /var/runtime/bootstrap 543 | RUN chmod +x /opt/bootstrap && chmod +x /var/runtime/bootstrap 544 | 545 | 546 | # Up until here the entire file has been designed as a top-down reading/execution. 547 | # Everything necessary for the `function` layer has been installed, isolated and 548 | # packaged. Now we'll go back one step and start from the extensions so that we 549 | # can install fpm. Then we'll start the fpm layer and quickly isolate fpm. 550 | 551 | FROM build-environment as fpm-extension 552 | 553 | RUN cp ${INSTALL_DIR}/sbin/php-fpm /bref-layer/bin/php-fpm 554 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bin/php-fpm /bref-layer/lib 555 | 556 | 557 | FROM isolation as fpm 558 | 559 | COPY --link --from=fpm-extension /bref-layer /opt 560 | 561 | COPY --link layers/fpm/bref.ini /opt/bref/etc/php/conf.d/ 562 | 563 | COPY --link layers/fpm/bootstrap.sh /opt/bootstrap 564 | # Copy files to /var/runtime to support deploying as a Docker image 565 | COPY --link layers/fpm/bootstrap.sh /var/runtime/bootstrap 566 | RUN chmod +x /opt/bootstrap && chmod +x /var/runtime/bootstrap 567 | 568 | COPY --link layers/fpm/php-fpm.conf /opt/bref/etc/php-fpm.conf 569 | -------------------------------------------------------------------------------- /php-82/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:1.4 2 | 3 | # Can be "x86_64" or "arm64" 4 | ARG IMAGE_VERSION_SUFFIX 5 | 6 | # https://www.php.net/downloads 7 | ARG VERSION_PHP=8.2.28 8 | 9 | 10 | # Lambda uses a custom AMI named Amazon Linux 2 11 | # https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html 12 | # AWS provides a Docker image that we use here: 13 | # https://github.com/amazonlinux/container-images/tree/amzn2 14 | FROM public.ecr.aws/lambda/provided:al2-${IMAGE_VERSION_SUFFIX} as build-environment 15 | 16 | 17 | RUN set -xe \ 18 | # Download yum repository data to cache 19 | && yum makecache \ 20 | # Install default development tools (gcc, make, etc) 21 | && yum groupinstall -y "Development Tools" --setopt=group_package_types=mandatory,default 22 | 23 | 24 | # The default version of cmake is 2.8.12. We need cmake to build a few of 25 | # our libraries, and at least one library requires a version of cmake greater than that. 26 | # Needed to build: 27 | # - libzip: minimum required CMAKE version 3.0. 28 | RUN LD_LIBRARY_PATH= yum install -y cmake3 29 | # Override the default `cmake` 30 | RUN ln -s /usr/bin/cmake3 /usr/bin/cmake 31 | 32 | 33 | # We need a base path for all the sourcecode we will build from. 34 | ENV BUILD_DIR="/tmp/build" 35 | 36 | # Target installation path for all the binaries and libraries we will compile. 37 | # We need to use /opt because that's where AWS Lambda layers are unzipped, 38 | # and we need binaries (e.g. /opt/bin/php) to look for libraries in /opt/lib. 39 | # Indeed, `/opt/lib` is a path Lambda looks for libraries by default (it is in `LD_LIBRARY_PATH`) 40 | # AND the `/opt/lib` path will be hardcoded in the compiled binaries and libraries (called "rpath"). 41 | # 42 | # Note: the /opt directory will be completely recreated from scratch in the final images, 43 | # so it's ok at this stage if we "pollute" it with plenty of extra libs/build artifacts. 44 | ENV INSTALL_DIR="/opt" 45 | 46 | # We need some default compiler variables setup 47 | ENV PKG_CONFIG_PATH="${INSTALL_DIR}/lib64/pkgconfig:${INSTALL_DIR}/lib/pkgconfig" \ 48 | PKG_CONFIG="/usr/bin/pkg-config" \ 49 | PATH="${INSTALL_DIR}/bin:${PATH}" 50 | 51 | ENV LD_LIBRARY_PATH="${INSTALL_DIR}/lib64:${INSTALL_DIR}/lib" 52 | 53 | # Enable parallelism by default for make and cmake (like make -j) 54 | # See https://stackoverflow.com/a/50883540/245552 55 | ENV CMAKE_BUILD_PARALLEL_LEVEL=4 56 | ENV MAKEFLAGS='-j4' 57 | 58 | # Ensure we have all the directories we require in the container. 59 | RUN mkdir -p ${BUILD_DIR} \ 60 | ${INSTALL_DIR}/bin \ 61 | ${INSTALL_DIR}/doc \ 62 | ${INSTALL_DIR}/etc/php \ 63 | ${INSTALL_DIR}/etc/php/conf.d \ 64 | ${INSTALL_DIR}/include \ 65 | ${INSTALL_DIR}/lib \ 66 | ${INSTALL_DIR}/lib64 \ 67 | ${INSTALL_DIR}/libexec \ 68 | ${INSTALL_DIR}/sbin \ 69 | ${INSTALL_DIR}/share 70 | 71 | 72 | ############################################################################### 73 | # ZLIB Build 74 | # We compile a newer version because Lambda uses an old version (1.2.7) that 75 | # has a security vulnerability (CVE-2022-37434). 76 | # See https://github.com/brefphp/aws-lambda-layers/pull/110 77 | # Can be removed once Lambda updates their version. 78 | # https://github.com/madler/zlib/releases 79 | ENV VERSION_ZLIB=1.3.1 80 | ENV ZLIB_BUILD_DIR=${BUILD_DIR}/zlib 81 | RUN set -xe; \ 82 | mkdir -p ${ZLIB_BUILD_DIR}; \ 83 | curl -Ls https://github.com/madler/zlib/releases/download/v${VERSION_ZLIB}/zlib-${VERSION_ZLIB}.tar.gz \ 84 | | tar xzC ${ZLIB_BUILD_DIR} --strip-components=1 85 | WORKDIR ${ZLIB_BUILD_DIR}/ 86 | RUN set -xe; \ 87 | make distclean \ 88 | && CFLAGS="" \ 89 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 90 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 91 | ./configure \ 92 | --prefix=${INSTALL_DIR} 93 | RUN set -xe; \ 94 | make install \ 95 | && rm ${INSTALL_DIR}/lib/libz.a 96 | 97 | 98 | ############################################################################### 99 | # OPENSSL 100 | # https://github.com/openssl/openssl/releases 101 | # Needs: 102 | # - zlib 103 | # Needed by: 104 | # - curl 105 | # - php 106 | RUN yum install -y perl-IPC-Cmd 107 | ENV VERSION_OPENSSL=3.3.3 108 | ENV OPENSSL_BUILD_DIR=${BUILD_DIR}/openssl 109 | ENV CA_BUNDLE_SOURCE="https://curl.se/ca/cacert.pem" 110 | ENV CA_BUNDLE="${INSTALL_DIR}/bref/ssl/cert.pem" 111 | RUN set -xe; \ 112 | mkdir -p ${OPENSSL_BUILD_DIR}; \ 113 | curl -Ls https://github.com/openssl/openssl/releases/download/openssl-${VERSION_OPENSSL}/openssl-${VERSION_OPENSSL}.tar.gz \ 114 | | tar xzC ${OPENSSL_BUILD_DIR} --strip-components=1 115 | WORKDIR ${OPENSSL_BUILD_DIR}/ 116 | RUN CFLAGS="" \ 117 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 118 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 119 | ./config \ 120 | --prefix=${INSTALL_DIR} \ 121 | --openssldir=${INSTALL_DIR}/bref/ssl \ 122 | --release \ 123 | enable-tls1_3 \ 124 | no-tests \ 125 | shared \ 126 | zlib 127 | # Explicitly compile make without parallelism because it fails if we use -jX (no error message) 128 | # I'm not 100% sure why, and I already lost 4 hours on this, but I found this: 129 | # https://github.com/openssl/openssl/issues/9931 130 | # https://stackoverflow.com/questions/28639207/why-cant-i-compile-openssl-with-multiple-threads-make-j3 131 | # Run `make install_sw install_ssldirs` instead of `make install` to skip installing man pages https://github.com/openssl/openssl/issues/8170 132 | RUN make -j1 install_sw install_ssldirs 133 | RUN mkdir -p ${INSTALL_DIR}/bref/ssl && curl -Lk -o ${CA_BUNDLE} ${CA_BUNDLE_SOURCE} 134 | 135 | 136 | ############################################################################### 137 | # LIBXML2 138 | # https://gitlab.gnome.org/GNOME/libxml2/-/releases 139 | # Uses: 140 | # - zlib 141 | # Needed by: 142 | # - php 143 | # - libnghttp2 144 | ENV VERSION_XML2=2.13.8 145 | ENV XML2_BUILD_DIR=${BUILD_DIR}/xml2 146 | RUN set -xe; \ 147 | mkdir -p ${XML2_BUILD_DIR}; \ 148 | curl -Ls https://download.gnome.org/sources/libxml2/${VERSION_XML2%.*}/libxml2-${VERSION_XML2}.tar.xz \ 149 | | tar xJC ${XML2_BUILD_DIR} --strip-components=1 150 | WORKDIR ${XML2_BUILD_DIR}/ 151 | RUN CFLAGS="" \ 152 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 153 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 154 | ./configure \ 155 | --prefix=${INSTALL_DIR} \ 156 | --with-sysroot=${INSTALL_DIR} \ 157 | --enable-shared \ 158 | --disable-static \ 159 | --with-html \ 160 | --with-history \ 161 | --enable-ipv6=no \ 162 | --with-icu \ 163 | --with-zlib \ 164 | --without-python 165 | RUN make install \ 166 | && cp xml2-config ${INSTALL_DIR}/bin/xml2-config 167 | 168 | 169 | ############################################################################### 170 | # LIBSSH2 171 | # https://github.com/libssh2/libssh2/releases 172 | # Needs: 173 | # - zlib 174 | # - OpenSSL 175 | # Needed by: 176 | # - curl 177 | ENV VERSION_LIBSSH2=1.11.1 178 | ENV LIBSSH2_BUILD_DIR=${BUILD_DIR}/libssh2 179 | RUN set -xe; \ 180 | mkdir -p ${LIBSSH2_BUILD_DIR}/bin; \ 181 | curl -Ls https://github.com/libssh2/libssh2/releases/download/libssh2-${VERSION_LIBSSH2}/libssh2-${VERSION_LIBSSH2}.tar.gz \ 182 | | tar xzC ${LIBSSH2_BUILD_DIR} --strip-components=1 183 | WORKDIR ${LIBSSH2_BUILD_DIR}/bin/ 184 | RUN CFLAGS="" \ 185 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 186 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 187 | cmake .. \ 188 | # Build as a shared library (.so) instead of a static one 189 | -DBUILD_SHARED_LIBS=ON \ 190 | # Build with OpenSSL support 191 | -DCRYPTO_BACKEND=OpenSSL \ 192 | # Build with zlib support 193 | -DENABLE_ZLIB_COMPRESSION=ON \ 194 | -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \ 195 | -DCMAKE_BUILD_TYPE=RELEASE 196 | RUN cmake --build . --target install 197 | 198 | 199 | ############################################################################### 200 | # LIBNGHTTP2 201 | # This adds support for HTTP 2 requests in curl. 202 | # See https://github.com/brefphp/bref/issues/727 and https://github.com/brefphp/bref/pull/740 203 | # https://github.com/nghttp2/nghttp2/releases 204 | # Needs: 205 | # - zlib 206 | # - OpenSSL 207 | # - libxml2 208 | # Needed by: 209 | # - curl 210 | ENV VERSION_NGHTTP2=1.65.0 211 | ENV NGHTTP2_BUILD_DIR=${BUILD_DIR}/nghttp2 212 | RUN set -xe; \ 213 | mkdir -p ${NGHTTP2_BUILD_DIR}; \ 214 | curl -Ls https://github.com/nghttp2/nghttp2/releases/download/v${VERSION_NGHTTP2}/nghttp2-${VERSION_NGHTTP2}.tar.gz \ 215 | | tar xzC ${NGHTTP2_BUILD_DIR} --strip-components=1 216 | WORKDIR ${NGHTTP2_BUILD_DIR}/ 217 | RUN CFLAGS="" \ 218 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 219 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 220 | ./configure \ 221 | --enable-lib-only \ 222 | --prefix=${INSTALL_DIR} 223 | RUN make install 224 | 225 | 226 | ############################################################################### 227 | # LIBPSL 228 | # This adds support for the public suffix list in curl. 229 | # https://github.com/rockdaboot/libpsl/releases 230 | # Needed by: 231 | # - curl 232 | ENV VERSION_LIBPSL=0.21.5 233 | ENV LIBPSL_BUILD_DIR=${BUILD_DIR}/libpsl 234 | RUN set -xe; \ 235 | mkdir -p ${LIBPSL_BUILD_DIR}; \ 236 | curl -Ls https://github.com/rockdaboot/libpsl/releases/download/${VERSION_LIBPSL}/libpsl-${VERSION_LIBPSL}.tar.gz \ 237 | | tar xzC ${LIBPSL_BUILD_DIR} --strip-components=1 238 | WORKDIR ${LIBPSL_BUILD_DIR}/ 239 | RUN CFLAGS="" \ 240 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 241 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 242 | ./configure \ 243 | --prefix=${INSTALL_DIR} 244 | RUN make -j $(nproc) && make install 245 | 246 | 247 | ############################################################################### 248 | # CURL 249 | # # https://github.com/curl/curl/releases 250 | # # Needs: 251 | # # - zlib 252 | # # - OpenSSL 253 | # # - libssh2 254 | # # - libnghttp2 255 | # # Needed by: 256 | # # - php 257 | ENV VERSION_CURL=8.14.1 258 | ENV CURL_BUILD_DIR=${BUILD_DIR}/curl 259 | RUN set -xe; \ 260 | mkdir -p ${CURL_BUILD_DIR}/bin; \ 261 | curl -Ls https://github.com/curl/curl/archive/curl-${VERSION_CURL//./_}.tar.gz \ 262 | | tar xzC ${CURL_BUILD_DIR} --strip-components=1 263 | WORKDIR ${CURL_BUILD_DIR}/ 264 | RUN ./buildconf \ 265 | && CFLAGS="" \ 266 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 267 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 268 | ./configure \ 269 | --prefix=${INSTALL_DIR} \ 270 | --with-ca-bundle=${CA_BUNDLE} \ 271 | --enable-shared \ 272 | --disable-static \ 273 | --enable-optimize \ 274 | --disable-warnings \ 275 | --disable-dependency-tracking \ 276 | --with-zlib \ 277 | --enable-http \ 278 | --enable-ftp \ 279 | --enable-file \ 280 | --enable-proxy \ 281 | --enable-tftp \ 282 | --enable-ipv6 \ 283 | --enable-openssl-auto-load-config \ 284 | --enable-cookies \ 285 | --with-gnu-ld \ 286 | --with-ssl \ 287 | --with-libssh2 \ 288 | --with-nghttp2 289 | RUN make install 290 | 291 | 292 | ############################################################################### 293 | # LIBZIP 294 | # https://github.com/nih-at/libzip/releases 295 | # Needed by: 296 | # - php 297 | ENV VERSION_ZIP=1.11.4 298 | ENV ZIP_BUILD_DIR=${BUILD_DIR}/zip 299 | RUN set -xe; \ 300 | mkdir -p ${ZIP_BUILD_DIR}/bin/; \ 301 | curl -Ls https://github.com/nih-at/libzip/releases/download/v${VERSION_ZIP}/libzip-${VERSION_ZIP}.tar.gz \ 302 | | tar xzC ${ZIP_BUILD_DIR} --strip-components=1 303 | WORKDIR ${ZIP_BUILD_DIR}/bin/ 304 | RUN CFLAGS="" \ 305 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 306 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 307 | cmake .. \ 308 | -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \ 309 | -DCMAKE_BUILD_TYPE=RELEASE 310 | RUN cmake --build . --target install 311 | 312 | 313 | ############################################################################### 314 | # LIBSODIUM 315 | # https://github.com/jedisct1/libsodium/releases 316 | # Needed by: 317 | # - php 318 | ENV VERSION_LIBSODIUM=1.0.20 319 | ENV LIBSODIUM_BUILD_DIR=${BUILD_DIR}/libsodium 320 | RUN set -xe; \ 321 | mkdir -p ${LIBSODIUM_BUILD_DIR}; \ 322 | curl -Ls https://github.com/jedisct1/libsodium/archive/${VERSION_LIBSODIUM}-RELEASE.tar.gz \ 323 | | tar xzC ${LIBSODIUM_BUILD_DIR} --strip-components=1 324 | WORKDIR ${LIBSODIUM_BUILD_DIR}/ 325 | RUN CFLAGS="" \ 326 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 327 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 328 | ./autogen.sh \ 329 | && ./configure --prefix=${INSTALL_DIR} 330 | RUN make install 331 | 332 | 333 | ############################################################################### 334 | # Postgres 335 | # https://github.com/postgres/postgres/tags 336 | # Needs: 337 | # - OpenSSL 338 | # Needed by: 339 | # - php 340 | ENV VERSION_POSTGRES=17.5 341 | ENV POSTGRES_BUILD_DIR=${BUILD_DIR}/postgres 342 | RUN set -xe; \ 343 | mkdir -p ${POSTGRES_BUILD_DIR}/bin; \ 344 | curl -Ls https://github.com/postgres/postgres/archive/REL_${VERSION_POSTGRES//./_}.tar.gz \ 345 | | tar xzC ${POSTGRES_BUILD_DIR} --strip-components=1 346 | WORKDIR ${POSTGRES_BUILD_DIR}/ 347 | RUN CFLAGS="" \ 348 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 349 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 350 | ./configure --prefix=${INSTALL_DIR} --with-openssl --without-icu --without-readline 351 | RUN cd ${POSTGRES_BUILD_DIR}/src/interfaces/libpq && make && make install 352 | RUN cd ${POSTGRES_BUILD_DIR}/src/bin/pg_config && make && make install 353 | RUN cd ${POSTGRES_BUILD_DIR}/src/backend && make generated-headers 354 | RUN cd ${POSTGRES_BUILD_DIR}/src/include && make install 355 | 356 | 357 | ############################################################################### 358 | # Oniguruma 359 | # This library is not packaged in PHP since PHP 7.4. 360 | # See https://github.com/php/php-src/blob/43dc7da8e3719d3e89bd8ec15ebb13f997bbbaa9/UPGRADING#L578-L581 361 | # We do not install the system version because I didn't manage to make it work... 362 | # Ideally we shouldn't compile it ourselves. 363 | # https://github.com/kkos/oniguruma/releases 364 | # Needed by: 365 | # - php mbstring 366 | ENV VERSION_ONIG=6.9.10 367 | ENV ONIG_BUILD_DIR=${BUILD_DIR}/oniguruma 368 | RUN set -xe; \ 369 | mkdir -p ${ONIG_BUILD_DIR}; \ 370 | curl -Ls https://github.com/kkos/oniguruma/releases/download/v${VERSION_ONIG}/onig-${VERSION_ONIG}.tar.gz \ 371 | | tar xzC ${ONIG_BUILD_DIR} --strip-components=1 372 | WORKDIR ${ONIG_BUILD_DIR} 373 | RUN ./configure --prefix=${INSTALL_DIR} 374 | RUN make && make install 375 | 376 | 377 | ############################################################################### 378 | # SQLite 379 | # Since PHP 7.4, libsqlite must be installed (https://github.com/php/php-src/blob/99b8e67615159fc600a615e1e97f2d1cf18f14cb/UPGRADING#L616-L619) 380 | # Laravel 11 requires SQLite 3.35.0 or higher and Drupal 10 also requires a 381 | # newer version than the system version of 3.7.17. 382 | # https://laravel.com/docs/11.x/upgrade#sqlite-minimum-version 383 | # https://www.sqlite.org/changes.html 384 | # Needed by: 385 | # - php 386 | RUN LD_LIBRARY_PATH= yum install -y tcl 387 | ENV VERSION_SQLITE=3.50.0 388 | ENV SQLITE_BUILD_DIR=${BUILD_DIR}/sqlite 389 | RUN set -xe; \ 390 | mkdir -p ${SQLITE_BUILD_DIR}; \ 391 | curl -Ls https://github.com/sqlite/sqlite/archive/refs/tags/version-${VERSION_SQLITE}.tar.gz \ 392 | | tar xzC ${SQLITE_BUILD_DIR} --strip-components=1 393 | WORKDIR ${SQLITE_BUILD_DIR} 394 | RUN ./configure --prefix=${INSTALL_DIR} 395 | RUN make && make install 396 | 397 | 398 | ############################################################################### 399 | # Install some dev files for using old libraries already on the system 400 | # readline-devel : needed for the readline extension 401 | # gettext-devel : needed for the --with-gettext flag 402 | # libicu-devel : needed for intl 403 | # libxslt-devel : needed for the XSL extension 404 | # libffi-devel : needed for the FFI extension 405 | RUN LD_LIBRARY_PATH= yum install -y readline-devel gettext-devel libicu-devel libxslt-devel libffi-devel 406 | 407 | 408 | # Note: this variable is used when building extra/custom extensions, do not remove 409 | ENV PHP_BUILD_DIR=/tmp/php 410 | 411 | # PHP Build 412 | # https://github.com/php/php-src/releases 413 | # Needs: 414 | # - zlib 415 | # - libxml2 416 | # - openssl 417 | # - readline 418 | # - sodium 419 | RUN mkdir -p ${PHP_BUILD_DIR} 420 | WORKDIR ${PHP_BUILD_DIR} 421 | 422 | # Download and unpack the source code 423 | # --location will follow redirects 424 | # --silent will hide the progress, but also the errors: we restore error messages with --show-error 425 | # --fail makes sure that curl returns an error instead of fetching the 404 page 426 | ARG VERSION_PHP 427 | RUN curl --location --silent --show-error --fail https://www.php.net/get/php-${VERSION_PHP}.tar.gz/from/this/mirror \ 428 | | tar xzC . --strip-components=1 429 | 430 | # Configure the build 431 | # -fstack-protector-strong : Be paranoid about stack overflows 432 | # -fpic : Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64) 433 | # -fpie : Support Address Space Layout Randomization (see -fpic) 434 | # -O3 : Optimize for fastest binaries possible. 435 | # -I : Add the path to the list of directories to be searched for header files during preprocessing. 436 | # --enable-option-checking=fatal: make sure invalid --configure-flags are fatal errors instead of just warnings 437 | # --enable-ftp: because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236) 438 | # --enable-mbstring: because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195) 439 | # --with-zlib and --with-zlib-dir: See https://stackoverflow.com/a/42978649/245552 440 | ARG PHP_COMPILATION_FLAGS 441 | RUN ./buildconf --force 442 | RUN CFLAGS="-fstack-protector-strong -fpic -fpie -O3 -I${INSTALL_DIR}/include -I/usr/include -ffunction-sections -fdata-sections" \ 443 | CPPFLAGS="-fstack-protector-strong -fpic -fpie -O3 -I${INSTALL_DIR}/include -I/usr/include -ffunction-sections -fdata-sections" \ 444 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib -Wl,-O1 -Wl,--strip-all -Wl,--hash-style=both -pie" \ 445 | ./configure \ 446 | --prefix=${INSTALL_DIR} \ 447 | --enable-option-checking=fatal \ 448 | --enable-sockets \ 449 | --with-config-file-path=/opt/bref/etc/php \ 450 | --with-config-file-scan-dir=/opt/bref/etc/php/conf.d:/var/task/php/conf.d \ 451 | --enable-fpm \ 452 | --disable-cgi \ 453 | --enable-cli \ 454 | --disable-phpdbg \ 455 | --with-sodium \ 456 | --with-readline \ 457 | --with-openssl \ 458 | --with-zlib \ 459 | --with-zlib-dir \ 460 | --with-curl \ 461 | --enable-exif \ 462 | --enable-ftp \ 463 | --with-gettext \ 464 | --enable-mbstring \ 465 | --with-pdo-mysql=shared,mysqlnd \ 466 | --with-mysqli \ 467 | --enable-pcntl \ 468 | --with-zip \ 469 | --enable-bcmath \ 470 | --with-pdo-pgsql=shared,${INSTALL_DIR} \ 471 | --enable-intl=shared \ 472 | --enable-soap \ 473 | --with-xsl=${INSTALL_DIR} \ 474 | --with-ffi \ 475 | # necessary for `pecl` to work (to install PHP extensions) 476 | --with-pear \ 477 | # extra compilation flags 478 | ${PHP_COMPILATION_FLAGS} 479 | RUN make -j $(nproc) 480 | # Run `make install` and override PEAR's PHAR URL because pear.php.net is down 481 | RUN set -xe; \ 482 | make install PEAR_INSTALLER_URL='https://github.com/pear/pearweb_phars/raw/master/install-pear-nozlib.phar'; \ 483 | { find ${INSTALL_DIR}/bin ${INSTALL_DIR}/sbin -type f -perm +0111 -exec strip --strip-all '{}' + || true; }; \ 484 | make clean; \ 485 | cp php.ini-production ${INSTALL_DIR}/etc/php/php.ini 486 | 487 | 488 | # Install extensions 489 | # We can install extensions manually or using `pecl` 490 | ENV VERSION_APCU=5.1.24 491 | RUN pecl install apcu-${VERSION_APCU} 492 | 493 | 494 | # --------------------------------------------------------------- 495 | # Now we copy everything we need for the layers into /bref-layer (which will be used for the real /opt later) 496 | RUN mkdir -p /bref-layer/bin \ 497 | && mkdir -p /bref-layer/lib \ 498 | && mkdir -p /bref-layer/bref/extensions \ 499 | && mkdir -p /bref-layer/bref/ssl 500 | 501 | # Copy the PHP binary 502 | RUN cp ${INSTALL_DIR}/bin/php /bref-layer/bin/php && chmod +x /bref-layer/bin/php 503 | 504 | # Copy all the external PHP extensions 505 | RUN cp $(php -r 'echo ini_get("extension_dir");')/* /bref-layer/bref/extensions/ 506 | 507 | # Copy all the required system libraries from: 508 | # - /lib | /lib64 (system libraries installed with `yum`) 509 | # - /opt/bin | /opt/lib | /opt/lib64 (libraries compiled from source) 510 | # into `/bref-layer` (the temp directory for the future Lambda layer) 511 | COPY --link utils/lib-copy /bref/lib-copy 512 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bin/php /bref-layer/lib 513 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/apcu.so /bref-layer/lib 514 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/intl.so /bref-layer/lib 515 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/opcache.so /bref-layer/lib 516 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/pdo_mysql.so /bref-layer/lib 517 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/pdo_pgsql.so /bref-layer/lib 518 | 519 | # Copy the OpenSSL certificates file 520 | RUN cp ${CA_BUNDLE} /bref-layer/bref/ssl/cert.pem 521 | 522 | # Copy the OpenSSL config 523 | RUN cp ${INSTALL_DIR}/bref/ssl/openssl.cnf /bref-layer/bref/ssl/openssl.cnf 524 | 525 | 526 | # --------------------------------------------------------------- 527 | # Start from a clean image to copy only the files we need 528 | FROM public.ecr.aws/lambda/provided:al2-${IMAGE_VERSION_SUFFIX} as isolation 529 | 530 | # We selected the files in /bref-layer, now we copy them to /opt (the real directory for the Lambda layer) 531 | COPY --link --from=build-environment /bref-layer /opt 532 | 533 | COPY --link layers/bootstrap.php /opt/bref/bootstrap.php 534 | 535 | 536 | FROM isolation as function 537 | 538 | COPY --link layers/function/bref.ini /opt/bref/etc/php/conf.d/ 539 | 540 | COPY --link layers/function/bootstrap.sh /opt/bootstrap 541 | # Copy files to /var/runtime to support deploying as a Docker image 542 | COPY --link layers/function/bootstrap.sh /var/runtime/bootstrap 543 | RUN chmod +x /opt/bootstrap && chmod +x /var/runtime/bootstrap 544 | 545 | 546 | # Up until here the entire file has been designed as a top-down reading/execution. 547 | # Everything necessary for the `function` layer has been installed, isolated and 548 | # packaged. Now we'll go back one step and start from the extensions so that we 549 | # can install fpm. Then we'll start the fpm layer and quickly isolate fpm. 550 | 551 | FROM build-environment as fpm-extension 552 | 553 | RUN cp ${INSTALL_DIR}/sbin/php-fpm /bref-layer/bin/php-fpm 554 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bin/php-fpm /bref-layer/lib 555 | 556 | 557 | FROM isolation as fpm 558 | 559 | COPY --link --from=fpm-extension /bref-layer /opt 560 | 561 | COPY --link layers/fpm/bref.ini /opt/bref/etc/php/conf.d/ 562 | 563 | COPY --link layers/fpm/bootstrap.sh /opt/bootstrap 564 | # Copy files to /var/runtime to support deploying as a Docker image 565 | COPY --link layers/fpm/bootstrap.sh /var/runtime/bootstrap 566 | RUN chmod +x /opt/bootstrap && chmod +x /var/runtime/bootstrap 567 | 568 | COPY --link layers/fpm/php-fpm.conf /opt/bref/etc/php-fpm.conf 569 | -------------------------------------------------------------------------------- /php-83/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:1.4 2 | 3 | # Can be "x86_64" or "arm64" 4 | ARG IMAGE_VERSION_SUFFIX 5 | 6 | # https://www.php.net/downloads 7 | ARG VERSION_PHP=8.3.22 8 | 9 | 10 | # Lambda uses a custom AMI named Amazon Linux 2 11 | # https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html 12 | # AWS provides a Docker image that we use here: 13 | # https://github.com/amazonlinux/container-images/tree/amzn2 14 | FROM public.ecr.aws/lambda/provided:al2-${IMAGE_VERSION_SUFFIX} as build-environment 15 | 16 | 17 | RUN set -xe \ 18 | # Download yum repository data to cache 19 | && yum makecache \ 20 | # Install default development tools (gcc, make, etc) 21 | && yum groupinstall -y "Development Tools" --setopt=group_package_types=mandatory,default 22 | 23 | 24 | # The default version of cmake is 2.8.12. We need cmake to build a few of 25 | # our libraries, and at least one library requires a version of cmake greater than that. 26 | # Needed to build: 27 | # - libzip: minimum required CMAKE version 3.0. 28 | RUN LD_LIBRARY_PATH= yum install -y cmake3 29 | # Override the default `cmake` 30 | RUN ln -s /usr/bin/cmake3 /usr/bin/cmake 31 | 32 | 33 | # We need a base path for all the sourcecode we will build from. 34 | ENV BUILD_DIR="/tmp/build" 35 | 36 | # Target installation path for all the binaries and libraries we will compile. 37 | # We need to use /opt because that's where AWS Lambda layers are unzipped, 38 | # and we need binaries (e.g. /opt/bin/php) to look for libraries in /opt/lib. 39 | # Indeed, `/opt/lib` is a path Lambda looks for libraries by default (it is in `LD_LIBRARY_PATH`) 40 | # AND the `/opt/lib` path will be hardcoded in the compiled binaries and libraries (called "rpath"). 41 | # 42 | # Note: the /opt directory will be completely recreated from scratch in the final images, 43 | # so it's ok at this stage if we "pollute" it with plenty of extra libs/build artifacts. 44 | ENV INSTALL_DIR="/opt" 45 | 46 | # We need some default compiler variables setup 47 | ENV PKG_CONFIG_PATH="${INSTALL_DIR}/lib64/pkgconfig:${INSTALL_DIR}/lib/pkgconfig" \ 48 | PKG_CONFIG="/usr/bin/pkg-config" \ 49 | PATH="${INSTALL_DIR}/bin:${PATH}" 50 | 51 | ENV LD_LIBRARY_PATH="${INSTALL_DIR}/lib64:${INSTALL_DIR}/lib" 52 | 53 | # Enable parallelism by default for make and cmake (like make -j) 54 | # See https://stackoverflow.com/a/50883540/245552 55 | ENV CMAKE_BUILD_PARALLEL_LEVEL=4 56 | ENV MAKEFLAGS='-j4' 57 | 58 | # Ensure we have all the directories we require in the container. 59 | RUN mkdir -p ${BUILD_DIR} \ 60 | ${INSTALL_DIR}/bin \ 61 | ${INSTALL_DIR}/doc \ 62 | ${INSTALL_DIR}/etc/php \ 63 | ${INSTALL_DIR}/etc/php/conf.d \ 64 | ${INSTALL_DIR}/include \ 65 | ${INSTALL_DIR}/lib \ 66 | ${INSTALL_DIR}/lib64 \ 67 | ${INSTALL_DIR}/libexec \ 68 | ${INSTALL_DIR}/sbin \ 69 | ${INSTALL_DIR}/share 70 | 71 | 72 | ############################################################################### 73 | # ZLIB Build 74 | # We compile a newer version because Lambda uses an old version (1.2.7) that 75 | # has a security vulnerability (CVE-2022-37434). 76 | # See https://github.com/brefphp/aws-lambda-layers/pull/110 77 | # Can be removed once Lambda updates their version. 78 | # https://github.com/madler/zlib/releases 79 | ENV VERSION_ZLIB=1.3.1 80 | ENV ZLIB_BUILD_DIR=${BUILD_DIR}/zlib 81 | RUN set -xe; \ 82 | mkdir -p ${ZLIB_BUILD_DIR}; \ 83 | curl -Ls https://github.com/madler/zlib/releases/download/v${VERSION_ZLIB}/zlib-${VERSION_ZLIB}.tar.gz \ 84 | | tar xzC ${ZLIB_BUILD_DIR} --strip-components=1 85 | WORKDIR ${ZLIB_BUILD_DIR}/ 86 | RUN set -xe; \ 87 | make distclean \ 88 | && CFLAGS="" \ 89 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 90 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 91 | ./configure \ 92 | --prefix=${INSTALL_DIR} 93 | RUN set -xe; \ 94 | make install \ 95 | && rm ${INSTALL_DIR}/lib/libz.a 96 | 97 | 98 | ############################################################################### 99 | # OPENSSL 100 | # https://github.com/openssl/openssl/releases 101 | # Needs: 102 | # - zlib 103 | # Needed by: 104 | # - curl 105 | # - php 106 | RUN yum install -y perl-IPC-Cmd 107 | ENV VERSION_OPENSSL=3.3.3 108 | ENV OPENSSL_BUILD_DIR=${BUILD_DIR}/openssl 109 | ENV CA_BUNDLE_SOURCE="https://curl.se/ca/cacert.pem" 110 | ENV CA_BUNDLE="${INSTALL_DIR}/bref/ssl/cert.pem" 111 | RUN set -xe; \ 112 | mkdir -p ${OPENSSL_BUILD_DIR}; \ 113 | curl -Ls https://github.com/openssl/openssl/releases/download/openssl-${VERSION_OPENSSL}/openssl-${VERSION_OPENSSL}.tar.gz \ 114 | | tar xzC ${OPENSSL_BUILD_DIR} --strip-components=1 115 | WORKDIR ${OPENSSL_BUILD_DIR}/ 116 | RUN CFLAGS="" \ 117 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 118 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 119 | ./config \ 120 | --prefix=${INSTALL_DIR} \ 121 | --openssldir=${INSTALL_DIR}/bref/ssl \ 122 | --release \ 123 | enable-tls1_3 \ 124 | no-tests \ 125 | shared \ 126 | zlib 127 | # Explicitly compile make without parallelism because it fails if we use -jX (no error message) 128 | # I'm not 100% sure why, and I already lost 4 hours on this, but I found this: 129 | # https://github.com/openssl/openssl/issues/9931 130 | # https://stackoverflow.com/questions/28639207/why-cant-i-compile-openssl-with-multiple-threads-make-j3 131 | # Run `make install_sw install_ssldirs` instead of `make install` to skip installing man pages https://github.com/openssl/openssl/issues/8170 132 | RUN make -j1 install_sw install_ssldirs 133 | RUN mkdir -p ${INSTALL_DIR}/bref/ssl && curl -Lk -o ${CA_BUNDLE} ${CA_BUNDLE_SOURCE} 134 | 135 | 136 | ############################################################################### 137 | # LIBXML2 138 | # https://gitlab.gnome.org/GNOME/libxml2/-/releases 139 | # Uses: 140 | # - zlib 141 | # Needed by: 142 | # - php 143 | # - libnghttp2 144 | ENV VERSION_XML2=2.13.8 145 | ENV XML2_BUILD_DIR=${BUILD_DIR}/xml2 146 | RUN set -xe; \ 147 | mkdir -p ${XML2_BUILD_DIR}; \ 148 | curl -Ls https://download.gnome.org/sources/libxml2/${VERSION_XML2%.*}/libxml2-${VERSION_XML2}.tar.xz \ 149 | | tar xJC ${XML2_BUILD_DIR} --strip-components=1 150 | WORKDIR ${XML2_BUILD_DIR}/ 151 | RUN CFLAGS="" \ 152 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 153 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 154 | ./configure \ 155 | --prefix=${INSTALL_DIR} \ 156 | --with-sysroot=${INSTALL_DIR} \ 157 | --enable-shared \ 158 | --disable-static \ 159 | --with-html \ 160 | --with-history \ 161 | --enable-ipv6=no \ 162 | --with-icu \ 163 | --with-zlib \ 164 | --without-python 165 | RUN make install \ 166 | && cp xml2-config ${INSTALL_DIR}/bin/xml2-config 167 | 168 | 169 | ############################################################################### 170 | # LIBSSH2 171 | # https://github.com/libssh2/libssh2/releases 172 | # Needs: 173 | # - zlib 174 | # - OpenSSL 175 | # Needed by: 176 | # - curl 177 | ENV VERSION_LIBSSH2=1.11.1 178 | ENV LIBSSH2_BUILD_DIR=${BUILD_DIR}/libssh2 179 | RUN set -xe; \ 180 | mkdir -p ${LIBSSH2_BUILD_DIR}/bin; \ 181 | curl -Ls https://github.com/libssh2/libssh2/releases/download/libssh2-${VERSION_LIBSSH2}/libssh2-${VERSION_LIBSSH2}.tar.gz \ 182 | | tar xzC ${LIBSSH2_BUILD_DIR} --strip-components=1 183 | WORKDIR ${LIBSSH2_BUILD_DIR}/bin/ 184 | RUN CFLAGS="" \ 185 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 186 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 187 | cmake .. \ 188 | # Build as a shared library (.so) instead of a static one 189 | -DBUILD_SHARED_LIBS=ON \ 190 | # Build with OpenSSL support 191 | -DCRYPTO_BACKEND=OpenSSL \ 192 | # Build with zlib support 193 | -DENABLE_ZLIB_COMPRESSION=ON \ 194 | -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \ 195 | -DCMAKE_BUILD_TYPE=RELEASE 196 | RUN cmake --build . --target install 197 | 198 | 199 | ############################################################################### 200 | # LIBNGHTTP2 201 | # This adds support for HTTP 2 requests in curl. 202 | # See https://github.com/brefphp/bref/issues/727 and https://github.com/brefphp/bref/pull/740 203 | # https://github.com/nghttp2/nghttp2/releases 204 | # Needs: 205 | # - zlib 206 | # - OpenSSL 207 | # - libxml2 208 | # Needed by: 209 | # - curl 210 | ENV VERSION_NGHTTP2=1.65.0 211 | ENV NGHTTP2_BUILD_DIR=${BUILD_DIR}/nghttp2 212 | RUN set -xe; \ 213 | mkdir -p ${NGHTTP2_BUILD_DIR}; \ 214 | curl -Ls https://github.com/nghttp2/nghttp2/releases/download/v${VERSION_NGHTTP2}/nghttp2-${VERSION_NGHTTP2}.tar.gz \ 215 | | tar xzC ${NGHTTP2_BUILD_DIR} --strip-components=1 216 | WORKDIR ${NGHTTP2_BUILD_DIR}/ 217 | RUN CFLAGS="" \ 218 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 219 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 220 | ./configure \ 221 | --enable-lib-only \ 222 | --prefix=${INSTALL_DIR} 223 | RUN make install 224 | 225 | 226 | ############################################################################### 227 | # LIBPSL 228 | # This adds support for the public suffix list in curl. 229 | # https://github.com/rockdaboot/libpsl/releases 230 | # Needed by: 231 | # - curl 232 | ENV VERSION_LIBPSL=0.21.5 233 | ENV LIBPSL_BUILD_DIR=${BUILD_DIR}/libpsl 234 | RUN set -xe; \ 235 | mkdir -p ${LIBPSL_BUILD_DIR}; \ 236 | curl -Ls https://github.com/rockdaboot/libpsl/releases/download/${VERSION_LIBPSL}/libpsl-${VERSION_LIBPSL}.tar.gz \ 237 | | tar xzC ${LIBPSL_BUILD_DIR} --strip-components=1 238 | WORKDIR ${LIBPSL_BUILD_DIR}/ 239 | RUN CFLAGS="" \ 240 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 241 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 242 | ./configure \ 243 | --prefix=${INSTALL_DIR} 244 | RUN make -j $(nproc) && make install 245 | 246 | 247 | ############################################################################### 248 | # CURL 249 | # # https://github.com/curl/curl/releases 250 | # # Needs: 251 | # # - zlib 252 | # # - OpenSSL 253 | # # - libssh2 254 | # # - libnghttp2 255 | # # Needed by: 256 | # # - php 257 | ENV VERSION_CURL=8.14.1 258 | ENV CURL_BUILD_DIR=${BUILD_DIR}/curl 259 | RUN set -xe; \ 260 | mkdir -p ${CURL_BUILD_DIR}/bin; \ 261 | curl -Ls https://github.com/curl/curl/archive/curl-${VERSION_CURL//./_}.tar.gz \ 262 | | tar xzC ${CURL_BUILD_DIR} --strip-components=1 263 | WORKDIR ${CURL_BUILD_DIR}/ 264 | RUN ./buildconf \ 265 | && CFLAGS="" \ 266 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 267 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 268 | ./configure \ 269 | --prefix=${INSTALL_DIR} \ 270 | --with-ca-bundle=${CA_BUNDLE} \ 271 | --enable-shared \ 272 | --disable-static \ 273 | --enable-optimize \ 274 | --disable-warnings \ 275 | --disable-dependency-tracking \ 276 | --with-zlib \ 277 | --enable-http \ 278 | --enable-ftp \ 279 | --enable-file \ 280 | --enable-proxy \ 281 | --enable-tftp \ 282 | --enable-ipv6 \ 283 | --enable-openssl-auto-load-config \ 284 | --enable-cookies \ 285 | --with-gnu-ld \ 286 | --with-ssl \ 287 | --with-libssh2 \ 288 | --with-nghttp2 289 | RUN make install 290 | 291 | 292 | ############################################################################### 293 | # LIBZIP 294 | # https://github.com/nih-at/libzip/releases 295 | # Needed by: 296 | # - php 297 | ENV VERSION_ZIP=1.11.4 298 | ENV ZIP_BUILD_DIR=${BUILD_DIR}/zip 299 | RUN set -xe; \ 300 | mkdir -p ${ZIP_BUILD_DIR}/bin/; \ 301 | curl -Ls https://github.com/nih-at/libzip/releases/download/v${VERSION_ZIP}/libzip-${VERSION_ZIP}.tar.gz \ 302 | | tar xzC ${ZIP_BUILD_DIR} --strip-components=1 303 | WORKDIR ${ZIP_BUILD_DIR}/bin/ 304 | RUN CFLAGS="" \ 305 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 306 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 307 | cmake .. \ 308 | -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \ 309 | -DCMAKE_BUILD_TYPE=RELEASE 310 | RUN cmake --build . --target install 311 | 312 | 313 | ############################################################################### 314 | # LIBSODIUM 315 | # https://github.com/jedisct1/libsodium/releases 316 | # Needed by: 317 | # - php 318 | ENV VERSION_LIBSODIUM=1.0.20 319 | ENV LIBSODIUM_BUILD_DIR=${BUILD_DIR}/libsodium 320 | RUN set -xe; \ 321 | mkdir -p ${LIBSODIUM_BUILD_DIR}; \ 322 | curl -Ls https://github.com/jedisct1/libsodium/archive/${VERSION_LIBSODIUM}-RELEASE.tar.gz \ 323 | | tar xzC ${LIBSODIUM_BUILD_DIR} --strip-components=1 324 | WORKDIR ${LIBSODIUM_BUILD_DIR}/ 325 | RUN CFLAGS="" \ 326 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 327 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 328 | ./autogen.sh \ 329 | && ./configure --prefix=${INSTALL_DIR} 330 | RUN make install 331 | 332 | 333 | ############################################################################### 334 | # Postgres 335 | # https://github.com/postgres/postgres/tags 336 | # Needs: 337 | # - OpenSSL 338 | # Needed by: 339 | # - php 340 | ENV VERSION_POSTGRES=17.5 341 | ENV POSTGRES_BUILD_DIR=${BUILD_DIR}/postgres 342 | RUN set -xe; \ 343 | mkdir -p ${POSTGRES_BUILD_DIR}/bin; \ 344 | curl -Ls https://github.com/postgres/postgres/archive/REL_${VERSION_POSTGRES//./_}.tar.gz \ 345 | | tar xzC ${POSTGRES_BUILD_DIR} --strip-components=1 346 | WORKDIR ${POSTGRES_BUILD_DIR}/ 347 | RUN CFLAGS="" \ 348 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 349 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 350 | ./configure --prefix=${INSTALL_DIR} --with-openssl --without-icu --without-readline 351 | RUN cd ${POSTGRES_BUILD_DIR}/src/interfaces/libpq && make && make install 352 | RUN cd ${POSTGRES_BUILD_DIR}/src/bin/pg_config && make && make install 353 | RUN cd ${POSTGRES_BUILD_DIR}/src/backend && make generated-headers 354 | RUN cd ${POSTGRES_BUILD_DIR}/src/include && make install 355 | 356 | 357 | ############################################################################### 358 | # Oniguruma 359 | # This library is not packaged in PHP since PHP 7.4. 360 | # See https://github.com/php/php-src/blob/43dc7da8e3719d3e89bd8ec15ebb13f997bbbaa9/UPGRADING#L578-L581 361 | # We do not install the system version because I didn't manage to make it work... 362 | # Ideally we shouldn't compile it ourselves. 363 | # https://github.com/kkos/oniguruma/releases 364 | # Needed by: 365 | # - php mbstring 366 | ENV VERSION_ONIG=6.9.10 367 | ENV ONIG_BUILD_DIR=${BUILD_DIR}/oniguruma 368 | RUN set -xe; \ 369 | mkdir -p ${ONIG_BUILD_DIR}; \ 370 | curl -Ls https://github.com/kkos/oniguruma/releases/download/v${VERSION_ONIG}/onig-${VERSION_ONIG}.tar.gz \ 371 | | tar xzC ${ONIG_BUILD_DIR} --strip-components=1 372 | WORKDIR ${ONIG_BUILD_DIR} 373 | RUN ./configure --prefix=${INSTALL_DIR} 374 | RUN make && make install 375 | 376 | 377 | ############################################################################### 378 | # SQLite 379 | # Since PHP 7.4, libsqlite must be installed (https://github.com/php/php-src/blob/99b8e67615159fc600a615e1e97f2d1cf18f14cb/UPGRADING#L616-L619) 380 | # Laravel 11 requires SQLite 3.35.0 or higher and Drupal 10 also requires a 381 | # newer version than the system version of 3.7.17. 382 | # https://laravel.com/docs/11.x/upgrade#sqlite-minimum-version 383 | # https://www.sqlite.org/changes.html 384 | # Needed by: 385 | # - php 386 | RUN LD_LIBRARY_PATH= yum install -y tcl 387 | ENV VERSION_SQLITE=3.50.0 388 | ENV SQLITE_BUILD_DIR=${BUILD_DIR}/sqlite 389 | RUN set -xe; \ 390 | mkdir -p ${SQLITE_BUILD_DIR}; \ 391 | curl -Ls https://github.com/sqlite/sqlite/archive/refs/tags/version-${VERSION_SQLITE}.tar.gz \ 392 | | tar xzC ${SQLITE_BUILD_DIR} --strip-components=1 393 | WORKDIR ${SQLITE_BUILD_DIR} 394 | RUN ./configure --prefix=${INSTALL_DIR} 395 | RUN make && make install 396 | 397 | 398 | ############################################################################### 399 | # Install some dev files for using old libraries already on the system 400 | # readline-devel : needed for the readline extension 401 | # gettext-devel : needed for the --with-gettext flag 402 | # libicu-devel : needed for intl 403 | # libxslt-devel : needed for the XSL extension 404 | # libffi-devel : needed for the FFI extension 405 | RUN LD_LIBRARY_PATH= yum install -y readline-devel gettext-devel libicu-devel libxslt-devel libffi-devel 406 | 407 | 408 | # Note: this variable is used when building extra/custom extensions, do not remove 409 | ENV PHP_BUILD_DIR=/tmp/php 410 | 411 | # PHP Build 412 | # https://github.com/php/php-src/releases 413 | # Needs: 414 | # - zlib 415 | # - libxml2 416 | # - openssl 417 | # - readline 418 | # - sodium 419 | RUN mkdir -p ${PHP_BUILD_DIR} 420 | WORKDIR ${PHP_BUILD_DIR} 421 | 422 | # Download and unpack the source code 423 | # --location will follow redirects 424 | # --silent will hide the progress, but also the errors: we restore error messages with --show-error 425 | # --fail makes sure that curl returns an error instead of fetching the 404 page 426 | ARG VERSION_PHP 427 | RUN curl --location --silent --show-error --fail https://www.php.net/get/php-${VERSION_PHP}.tar.gz/from/this/mirror \ 428 | | tar xzC . --strip-components=1 429 | 430 | # Configure the build 431 | # -fstack-protector-strong : Be paranoid about stack overflows 432 | # -fpic : Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64) 433 | # -fpie : Support Address Space Layout Randomization (see -fpic) 434 | # -O3 : Optimize for fastest binaries possible. 435 | # -I : Add the path to the list of directories to be searched for header files during preprocessing. 436 | # --enable-option-checking=fatal: make sure invalid --configure-flags are fatal errors instead of just warnings 437 | # --enable-ftp: because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236) 438 | # --enable-mbstring: because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195) 439 | # --with-zlib and --with-zlib-dir: See https://stackoverflow.com/a/42978649/245552 440 | ARG PHP_COMPILATION_FLAGS 441 | RUN ./buildconf --force 442 | RUN CFLAGS="-fstack-protector-strong -fpic -fpie -O3 -I${INSTALL_DIR}/include -I/usr/include -ffunction-sections -fdata-sections" \ 443 | CPPFLAGS="-fstack-protector-strong -fpic -fpie -O3 -I${INSTALL_DIR}/include -I/usr/include -ffunction-sections -fdata-sections" \ 444 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib -Wl,-O1 -Wl,--strip-all -Wl,--hash-style=both -pie" \ 445 | ./configure \ 446 | --prefix=${INSTALL_DIR} \ 447 | --enable-option-checking=fatal \ 448 | --enable-sockets \ 449 | --with-config-file-path=/opt/bref/etc/php \ 450 | --with-config-file-scan-dir=/opt/bref/etc/php/conf.d:/var/task/php/conf.d \ 451 | --enable-fpm \ 452 | --disable-cgi \ 453 | --enable-cli \ 454 | --disable-phpdbg \ 455 | --with-sodium \ 456 | --with-readline \ 457 | --with-openssl \ 458 | --with-zlib \ 459 | --with-zlib-dir \ 460 | --with-curl \ 461 | --enable-exif \ 462 | --enable-ftp \ 463 | --with-gettext \ 464 | --enable-mbstring \ 465 | --with-pdo-mysql=shared,mysqlnd \ 466 | --with-mysqli \ 467 | --enable-pcntl \ 468 | --with-zip \ 469 | --enable-bcmath \ 470 | --with-pdo-pgsql=shared,${INSTALL_DIR} \ 471 | --enable-intl=shared \ 472 | --enable-soap \ 473 | --with-xsl=${INSTALL_DIR} \ 474 | --with-ffi \ 475 | # necessary for `pecl` to work (to install PHP extensions) 476 | --with-pear \ 477 | # extra compilation flags 478 | ${PHP_COMPILATION_FLAGS} 479 | RUN make -j $(nproc) 480 | # Run `make install` and override PEAR's PHAR URL because pear.php.net is down 481 | RUN set -xe; \ 482 | make install PEAR_INSTALLER_URL='https://github.com/pear/pearweb_phars/raw/master/install-pear-nozlib.phar'; \ 483 | { find ${INSTALL_DIR}/bin ${INSTALL_DIR}/sbin -type f -perm +0111 -exec strip --strip-all '{}' + || true; }; \ 484 | make clean; \ 485 | cp php.ini-production ${INSTALL_DIR}/etc/php/php.ini 486 | 487 | 488 | # Install extensions 489 | # We can install extensions manually or using `pecl` 490 | ENV VERSION_APCU=5.1.24 491 | RUN pecl install apcu-${VERSION_APCU} 492 | 493 | 494 | # --------------------------------------------------------------- 495 | # Now we copy everything we need for the layers into /bref-layer (which will be used for the real /opt later) 496 | RUN mkdir -p /bref-layer/bin \ 497 | && mkdir -p /bref-layer/lib \ 498 | && mkdir -p /bref-layer/bref/extensions \ 499 | && mkdir -p /bref-layer/bref/ssl 500 | 501 | # Copy the PHP binary 502 | RUN cp ${INSTALL_DIR}/bin/php /bref-layer/bin/php && chmod +x /bref-layer/bin/php 503 | 504 | # Copy all the external PHP extensions 505 | RUN cp $(php -r 'echo ini_get("extension_dir");')/* /bref-layer/bref/extensions/ 506 | 507 | # Copy all the required system libraries from: 508 | # - /lib | /lib64 (system libraries installed with `yum`) 509 | # - /opt/bin | /opt/lib | /opt/lib64 (libraries compiled from source) 510 | # into `/bref-layer` (the temp directory for the future Lambda layer) 511 | COPY --link utils/lib-copy /bref/lib-copy 512 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bin/php /bref-layer/lib 513 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/apcu.so /bref-layer/lib 514 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/intl.so /bref-layer/lib 515 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/opcache.so /bref-layer/lib 516 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/pdo_mysql.so /bref-layer/lib 517 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/pdo_pgsql.so /bref-layer/lib 518 | 519 | # Copy the OpenSSL certificates file 520 | RUN cp ${CA_BUNDLE} /bref-layer/bref/ssl/cert.pem 521 | 522 | # Copy the OpenSSL config 523 | RUN cp ${INSTALL_DIR}/bref/ssl/openssl.cnf /bref-layer/bref/ssl/openssl.cnf 524 | 525 | 526 | # --------------------------------------------------------------- 527 | # Start from a clean image to copy only the files we need 528 | FROM public.ecr.aws/lambda/provided:al2-${IMAGE_VERSION_SUFFIX} as isolation 529 | 530 | # We selected the files in /bref-layer, now we copy them to /opt (the real directory for the Lambda layer) 531 | COPY --link --from=build-environment /bref-layer /opt 532 | 533 | COPY --link layers/bootstrap.php /opt/bref/bootstrap.php 534 | 535 | 536 | FROM isolation as function 537 | 538 | COPY --link layers/function/bref.ini /opt/bref/etc/php/conf.d/ 539 | 540 | COPY --link layers/function/bootstrap.sh /opt/bootstrap 541 | # Copy files to /var/runtime to support deploying as a Docker image 542 | COPY --link layers/function/bootstrap.sh /var/runtime/bootstrap 543 | RUN chmod +x /opt/bootstrap && chmod +x /var/runtime/bootstrap 544 | 545 | 546 | # Up until here the entire file has been designed as a top-down reading/execution. 547 | # Everything necessary for the `function` layer has been installed, isolated and 548 | # packaged. Now we'll go back one step and start from the extensions so that we 549 | # can install fpm. Then we'll start the fpm layer and quickly isolate fpm. 550 | 551 | FROM build-environment as fpm-extension 552 | 553 | RUN cp ${INSTALL_DIR}/sbin/php-fpm /bref-layer/bin/php-fpm 554 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bin/php-fpm /bref-layer/lib 555 | 556 | 557 | FROM isolation as fpm 558 | 559 | COPY --link --from=fpm-extension /bref-layer /opt 560 | 561 | COPY --link layers/fpm/bref.ini /opt/bref/etc/php/conf.d/ 562 | 563 | COPY --link layers/fpm/bootstrap.sh /opt/bootstrap 564 | # Copy files to /var/runtime to support deploying as a Docker image 565 | COPY --link layers/fpm/bootstrap.sh /var/runtime/bootstrap 566 | RUN chmod +x /opt/bootstrap && chmod +x /var/runtime/bootstrap 567 | 568 | COPY --link layers/fpm/php-fpm.conf /opt/bref/etc/php-fpm.conf 569 | -------------------------------------------------------------------------------- /php-84/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:1.4 2 | 3 | # Can be "x86_64" or "arm64" 4 | ARG IMAGE_VERSION_SUFFIX 5 | 6 | # https://www.php.net/downloads 7 | ARG VERSION_PHP=8.4.8 8 | 9 | 10 | # Lambda uses a custom AMI named Amazon Linux 2 11 | # https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html 12 | # AWS provides a Docker image that we use here: 13 | # https://github.com/amazonlinux/container-images/tree/amzn2 14 | FROM public.ecr.aws/lambda/provided:al2-${IMAGE_VERSION_SUFFIX} as build-environment 15 | 16 | 17 | RUN set -xe \ 18 | # Download yum repository data to cache 19 | && yum makecache \ 20 | # Install default development tools (gcc, make, etc) 21 | && yum groupinstall -y "Development Tools" --setopt=group_package_types=mandatory,default 22 | 23 | 24 | # The default version of cmake is 2.8.12. We need cmake to build a few of 25 | # our libraries, and at least one library requires a version of cmake greater than that. 26 | # Needed to build: 27 | # - libzip: minimum required CMAKE version 3.0. 28 | RUN LD_LIBRARY_PATH= yum install -y cmake3 29 | # Override the default `cmake` 30 | RUN ln -s /usr/bin/cmake3 /usr/bin/cmake 31 | 32 | 33 | # We need a base path for all the sourcecode we will build from. 34 | ENV BUILD_DIR="/tmp/build" 35 | 36 | # Target installation path for all the binaries and libraries we will compile. 37 | # We need to use /opt because that's where AWS Lambda layers are unzipped, 38 | # and we need binaries (e.g. /opt/bin/php) to look for libraries in /opt/lib. 39 | # Indeed, `/opt/lib` is a path Lambda looks for libraries by default (it is in `LD_LIBRARY_PATH`) 40 | # AND the `/opt/lib` path will be hardcoded in the compiled binaries and libraries (called "rpath"). 41 | # 42 | # Note: the /opt directory will be completely recreated from scratch in the final images, 43 | # so it's ok at this stage if we "pollute" it with plenty of extra libs/build artifacts. 44 | ENV INSTALL_DIR="/opt" 45 | 46 | # We need some default compiler variables setup 47 | ENV PKG_CONFIG_PATH="${INSTALL_DIR}/lib64/pkgconfig:${INSTALL_DIR}/lib/pkgconfig" \ 48 | PKG_CONFIG="/usr/bin/pkg-config" \ 49 | PATH="${INSTALL_DIR}/bin:${PATH}" 50 | 51 | ENV LD_LIBRARY_PATH="${INSTALL_DIR}/lib64:${INSTALL_DIR}/lib" 52 | 53 | # Enable parallelism by default for make and cmake (like make -j) 54 | # See https://stackoverflow.com/a/50883540/245552 55 | ENV CMAKE_BUILD_PARALLEL_LEVEL=4 56 | ENV MAKEFLAGS='-j4' 57 | 58 | # Ensure we have all the directories we require in the container. 59 | RUN mkdir -p ${BUILD_DIR} \ 60 | ${INSTALL_DIR}/bin \ 61 | ${INSTALL_DIR}/doc \ 62 | ${INSTALL_DIR}/etc/php \ 63 | ${INSTALL_DIR}/etc/php/conf.d \ 64 | ${INSTALL_DIR}/include \ 65 | ${INSTALL_DIR}/lib \ 66 | ${INSTALL_DIR}/lib64 \ 67 | ${INSTALL_DIR}/libexec \ 68 | ${INSTALL_DIR}/sbin \ 69 | ${INSTALL_DIR}/share 70 | 71 | 72 | ############################################################################### 73 | # ZLIB Build 74 | # We compile a newer version because Lambda uses an old version (1.2.7) that 75 | # has a security vulnerability (CVE-2022-37434). 76 | # See https://github.com/brefphp/aws-lambda-layers/pull/110 77 | # Can be removed once Lambda updates their version. 78 | # https://github.com/madler/zlib/releases 79 | ENV VERSION_ZLIB=1.3.1 80 | ENV ZLIB_BUILD_DIR=${BUILD_DIR}/zlib 81 | RUN set -xe; \ 82 | mkdir -p ${ZLIB_BUILD_DIR}; \ 83 | curl -Ls https://github.com/madler/zlib/releases/download/v${VERSION_ZLIB}/zlib-${VERSION_ZLIB}.tar.gz \ 84 | | tar xzC ${ZLIB_BUILD_DIR} --strip-components=1 85 | WORKDIR ${ZLIB_BUILD_DIR}/ 86 | RUN set -xe; \ 87 | make distclean \ 88 | && CFLAGS="" \ 89 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 90 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 91 | ./configure \ 92 | --prefix=${INSTALL_DIR} 93 | RUN set -xe; \ 94 | make install \ 95 | && rm ${INSTALL_DIR}/lib/libz.a 96 | 97 | 98 | ############################################################################### 99 | # OPENSSL 100 | # https://github.com/openssl/openssl/releases 101 | # Needs: 102 | # - zlib 103 | # Needed by: 104 | # - curl 105 | # - php 106 | RUN yum install -y perl-IPC-Cmd 107 | ENV VERSION_OPENSSL=3.3.3 108 | ENV OPENSSL_BUILD_DIR=${BUILD_DIR}/openssl 109 | ENV CA_BUNDLE_SOURCE="https://curl.se/ca/cacert.pem" 110 | ENV CA_BUNDLE="${INSTALL_DIR}/bref/ssl/cert.pem" 111 | RUN set -xe; \ 112 | mkdir -p ${OPENSSL_BUILD_DIR}; \ 113 | curl -Ls https://github.com/openssl/openssl/releases/download/openssl-${VERSION_OPENSSL}/openssl-${VERSION_OPENSSL}.tar.gz \ 114 | | tar xzC ${OPENSSL_BUILD_DIR} --strip-components=1 115 | WORKDIR ${OPENSSL_BUILD_DIR}/ 116 | RUN CFLAGS="" \ 117 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 118 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 119 | ./config \ 120 | --prefix=${INSTALL_DIR} \ 121 | --openssldir=${INSTALL_DIR}/bref/ssl \ 122 | --release \ 123 | enable-tls1_3 \ 124 | no-tests \ 125 | shared \ 126 | zlib 127 | # Explicitly compile make without parallelism because it fails if we use -jX (no error message) 128 | # I'm not 100% sure why, and I already lost 4 hours on this, but I found this: 129 | # https://github.com/openssl/openssl/issues/9931 130 | # https://stackoverflow.com/questions/28639207/why-cant-i-compile-openssl-with-multiple-threads-make-j3 131 | # Run `make install_sw install_ssldirs` instead of `make install` to skip installing man pages https://github.com/openssl/openssl/issues/8170 132 | RUN make -j1 install_sw install_ssldirs 133 | RUN mkdir -p ${INSTALL_DIR}/bref/ssl && curl -Lk -o ${CA_BUNDLE} ${CA_BUNDLE_SOURCE} 134 | 135 | 136 | ############################################################################### 137 | # LIBXML2 138 | # https://gitlab.gnome.org/GNOME/libxml2/-/releases 139 | # Uses: 140 | # - zlib 141 | # Needed by: 142 | # - php 143 | # - libnghttp2 144 | ENV VERSION_XML2=2.13.8 145 | ENV XML2_BUILD_DIR=${BUILD_DIR}/xml2 146 | RUN set -xe; \ 147 | mkdir -p ${XML2_BUILD_DIR}; \ 148 | curl -Ls https://download.gnome.org/sources/libxml2/${VERSION_XML2%.*}/libxml2-${VERSION_XML2}.tar.xz \ 149 | | tar xJC ${XML2_BUILD_DIR} --strip-components=1 150 | WORKDIR ${XML2_BUILD_DIR}/ 151 | RUN CFLAGS="" \ 152 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 153 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 154 | ./configure \ 155 | --prefix=${INSTALL_DIR} \ 156 | --with-sysroot=${INSTALL_DIR} \ 157 | --enable-shared \ 158 | --disable-static \ 159 | --with-html \ 160 | --with-history \ 161 | --enable-ipv6=no \ 162 | --with-icu \ 163 | --with-zlib \ 164 | --without-python 165 | RUN make install \ 166 | && cp xml2-config ${INSTALL_DIR}/bin/xml2-config 167 | 168 | 169 | ############################################################################### 170 | # LIBSSH2 171 | # https://github.com/libssh2/libssh2/releases 172 | # Needs: 173 | # - zlib 174 | # - OpenSSL 175 | # Needed by: 176 | # - curl 177 | ENV VERSION_LIBSSH2=1.11.1 178 | ENV LIBSSH2_BUILD_DIR=${BUILD_DIR}/libssh2 179 | RUN set -xe; \ 180 | mkdir -p ${LIBSSH2_BUILD_DIR}/bin; \ 181 | curl -Ls https://github.com/libssh2/libssh2/releases/download/libssh2-${VERSION_LIBSSH2}/libssh2-${VERSION_LIBSSH2}.tar.gz \ 182 | | tar xzC ${LIBSSH2_BUILD_DIR} --strip-components=1 183 | WORKDIR ${LIBSSH2_BUILD_DIR}/bin/ 184 | RUN CFLAGS="" \ 185 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 186 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 187 | cmake .. \ 188 | # Build as a shared library (.so) instead of a static one 189 | -DBUILD_SHARED_LIBS=ON \ 190 | # Build with OpenSSL support 191 | -DCRYPTO_BACKEND=OpenSSL \ 192 | # Build with zlib support 193 | -DENABLE_ZLIB_COMPRESSION=ON \ 194 | -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \ 195 | -DCMAKE_BUILD_TYPE=RELEASE 196 | RUN cmake --build . --target install 197 | 198 | 199 | ############################################################################### 200 | # LIBNGHTTP2 201 | # This adds support for HTTP 2 requests in curl. 202 | # See https://github.com/brefphp/bref/issues/727 and https://github.com/brefphp/bref/pull/740 203 | # https://github.com/nghttp2/nghttp2/releases 204 | # Needs: 205 | # - zlib 206 | # - OpenSSL 207 | # - libxml2 208 | # Needed by: 209 | # - curl 210 | ENV VERSION_NGHTTP2=1.65.0 211 | ENV NGHTTP2_BUILD_DIR=${BUILD_DIR}/nghttp2 212 | RUN set -xe; \ 213 | mkdir -p ${NGHTTP2_BUILD_DIR}; \ 214 | curl -Ls https://github.com/nghttp2/nghttp2/releases/download/v${VERSION_NGHTTP2}/nghttp2-${VERSION_NGHTTP2}.tar.gz \ 215 | | tar xzC ${NGHTTP2_BUILD_DIR} --strip-components=1 216 | WORKDIR ${NGHTTP2_BUILD_DIR}/ 217 | RUN CFLAGS="" \ 218 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 219 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 220 | ./configure \ 221 | --enable-lib-only \ 222 | --prefix=${INSTALL_DIR} 223 | RUN make install 224 | 225 | 226 | ############################################################################### 227 | # LIBPSL 228 | # This adds support for the public suffix list in curl. 229 | # https://github.com/rockdaboot/libpsl/releases 230 | # Needed by: 231 | # - curl 232 | ENV VERSION_LIBPSL=0.21.5 233 | ENV LIBPSL_BUILD_DIR=${BUILD_DIR}/libpsl 234 | RUN set -xe; \ 235 | mkdir -p ${LIBPSL_BUILD_DIR}; \ 236 | curl -Ls https://github.com/rockdaboot/libpsl/releases/download/${VERSION_LIBPSL}/libpsl-${VERSION_LIBPSL}.tar.gz \ 237 | | tar xzC ${LIBPSL_BUILD_DIR} --strip-components=1 238 | WORKDIR ${LIBPSL_BUILD_DIR}/ 239 | RUN CFLAGS="" \ 240 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 241 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 242 | ./configure \ 243 | --prefix=${INSTALL_DIR} 244 | RUN make -j $(nproc) && make install 245 | 246 | 247 | ############################################################################### 248 | # CURL 249 | # # https://github.com/curl/curl/releases 250 | # # Needs: 251 | # # - zlib 252 | # # - OpenSSL 253 | # # - libssh2 254 | # # - libnghttp2 255 | # # Needed by: 256 | # # - php 257 | ENV VERSION_CURL=8.14.1 258 | ENV CURL_BUILD_DIR=${BUILD_DIR}/curl 259 | RUN set -xe; \ 260 | mkdir -p ${CURL_BUILD_DIR}/bin; \ 261 | curl -Ls https://github.com/curl/curl/archive/curl-${VERSION_CURL//./_}.tar.gz \ 262 | | tar xzC ${CURL_BUILD_DIR} --strip-components=1 263 | WORKDIR ${CURL_BUILD_DIR}/ 264 | RUN ./buildconf \ 265 | && CFLAGS="" \ 266 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 267 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 268 | ./configure \ 269 | --prefix=${INSTALL_DIR} \ 270 | --with-ca-bundle=${CA_BUNDLE} \ 271 | --enable-shared \ 272 | --disable-static \ 273 | --enable-optimize \ 274 | --disable-warnings \ 275 | --disable-dependency-tracking \ 276 | --with-zlib \ 277 | --enable-http \ 278 | --enable-ftp \ 279 | --enable-file \ 280 | --enable-proxy \ 281 | --enable-tftp \ 282 | --enable-ipv6 \ 283 | --enable-openssl-auto-load-config \ 284 | --enable-cookies \ 285 | --with-gnu-ld \ 286 | --with-ssl \ 287 | --with-libssh2 \ 288 | --with-nghttp2 289 | RUN make install 290 | 291 | 292 | ############################################################################### 293 | # LIBZIP 294 | # https://github.com/nih-at/libzip/releases 295 | # Needed by: 296 | # - php 297 | ENV VERSION_ZIP=1.11.4 298 | ENV ZIP_BUILD_DIR=${BUILD_DIR}/zip 299 | RUN set -xe; \ 300 | mkdir -p ${ZIP_BUILD_DIR}/bin/; \ 301 | curl -Ls https://github.com/nih-at/libzip/releases/download/v${VERSION_ZIP}/libzip-${VERSION_ZIP}.tar.gz \ 302 | | tar xzC ${ZIP_BUILD_DIR} --strip-components=1 303 | WORKDIR ${ZIP_BUILD_DIR}/bin/ 304 | RUN CFLAGS="" \ 305 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 306 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 307 | cmake .. \ 308 | -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \ 309 | -DCMAKE_BUILD_TYPE=RELEASE 310 | RUN cmake --build . --target install 311 | 312 | 313 | ############################################################################### 314 | # LIBSODIUM 315 | # https://github.com/jedisct1/libsodium/releases 316 | # Needed by: 317 | # - php 318 | ENV VERSION_LIBSODIUM=1.0.20 319 | ENV LIBSODIUM_BUILD_DIR=${BUILD_DIR}/libsodium 320 | RUN set -xe; \ 321 | mkdir -p ${LIBSODIUM_BUILD_DIR}; \ 322 | curl -Ls https://github.com/jedisct1/libsodium/archive/${VERSION_LIBSODIUM}-RELEASE.tar.gz \ 323 | | tar xzC ${LIBSODIUM_BUILD_DIR} --strip-components=1 324 | WORKDIR ${LIBSODIUM_BUILD_DIR}/ 325 | RUN CFLAGS="" \ 326 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 327 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 328 | ./autogen.sh \ 329 | && ./configure --prefix=${INSTALL_DIR} 330 | RUN make install 331 | 332 | 333 | ############################################################################### 334 | # Postgres 335 | # https://github.com/postgres/postgres/tags 336 | # Needs: 337 | # - OpenSSL 338 | # Needed by: 339 | # - php 340 | ENV VERSION_POSTGRES=17.5 341 | ENV POSTGRES_BUILD_DIR=${BUILD_DIR}/postgres 342 | RUN set -xe; \ 343 | mkdir -p ${POSTGRES_BUILD_DIR}/bin; \ 344 | curl -Ls https://github.com/postgres/postgres/archive/REL_${VERSION_POSTGRES//./_}.tar.gz \ 345 | | tar xzC ${POSTGRES_BUILD_DIR} --strip-components=1 346 | WORKDIR ${POSTGRES_BUILD_DIR}/ 347 | RUN CFLAGS="" \ 348 | CPPFLAGS="-I${INSTALL_DIR}/include -I/usr/include" \ 349 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib" \ 350 | ./configure --prefix=${INSTALL_DIR} --with-openssl --without-icu --without-readline 351 | RUN cd ${POSTGRES_BUILD_DIR}/src/interfaces/libpq && make && make install 352 | RUN cd ${POSTGRES_BUILD_DIR}/src/bin/pg_config && make && make install 353 | RUN cd ${POSTGRES_BUILD_DIR}/src/backend && make generated-headers 354 | RUN cd ${POSTGRES_BUILD_DIR}/src/include && make install 355 | 356 | 357 | ############################################################################### 358 | # Oniguruma 359 | # This library is not packaged in PHP since PHP 7.4. 360 | # See https://github.com/php/php-src/blob/43dc7da8e3719d3e89bd8ec15ebb13f997bbbaa9/UPGRADING#L578-L581 361 | # We do not install the system version because I didn't manage to make it work... 362 | # Ideally we shouldn't compile it ourselves. 363 | # https://github.com/kkos/oniguruma/releases 364 | # Needed by: 365 | # - php mbstring 366 | ENV VERSION_ONIG=6.9.10 367 | ENV ONIG_BUILD_DIR=${BUILD_DIR}/oniguruma 368 | RUN set -xe; \ 369 | mkdir -p ${ONIG_BUILD_DIR}; \ 370 | curl -Ls https://github.com/kkos/oniguruma/releases/download/v${VERSION_ONIG}/onig-${VERSION_ONIG}.tar.gz \ 371 | | tar xzC ${ONIG_BUILD_DIR} --strip-components=1 372 | WORKDIR ${ONIG_BUILD_DIR} 373 | RUN ./configure --prefix=${INSTALL_DIR} 374 | RUN make && make install 375 | 376 | 377 | ############################################################################### 378 | # SQLite 379 | # Since PHP 7.4, libsqlite must be installed (https://github.com/php/php-src/blob/99b8e67615159fc600a615e1e97f2d1cf18f14cb/UPGRADING#L616-L619) 380 | # PHP 8.4 requires SQLite 3.13.0 or higher because the build uses the 381 | # `SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION` constant. 382 | # See https://github.com/brefphp/aws-lambda-layers/pull/185 383 | # Laravel 11 requires SQLite 3.35.0 or higher and Drupal 10 also requires a 384 | # newer version than the system version of 3.7.17. 385 | # https://laravel.com/docs/11.x/upgrade#sqlite-minimum-version 386 | # https://www.sqlite.org/changes.html 387 | # Needed by: 388 | # - php 389 | RUN LD_LIBRARY_PATH= yum install -y tcl 390 | ENV VERSION_SQLITE=3.50.0 391 | ENV SQLITE_BUILD_DIR=${BUILD_DIR}/sqlite 392 | RUN set -xe; \ 393 | mkdir -p ${SQLITE_BUILD_DIR}; \ 394 | curl -Ls https://github.com/sqlite/sqlite/archive/refs/tags/version-${VERSION_SQLITE}.tar.gz \ 395 | | tar xzC ${SQLITE_BUILD_DIR} --strip-components=1 396 | WORKDIR ${SQLITE_BUILD_DIR} 397 | RUN ./configure --prefix=${INSTALL_DIR} 398 | RUN make && make install 399 | 400 | 401 | ############################################################################### 402 | # Install some dev files for using old libraries already on the system 403 | # readline-devel : needed for the readline extension 404 | # gettext-devel : needed for the --with-gettext flag 405 | # libicu-devel : needed for intl 406 | # libxslt-devel : needed for the XSL extension 407 | # libffi-devel : needed for the FFI extension 408 | RUN LD_LIBRARY_PATH= yum install -y readline-devel gettext-devel libicu-devel libxslt-devel libffi-devel 409 | 410 | 411 | # Note: this variable is used when building extra/custom extensions, do not remove 412 | ENV PHP_BUILD_DIR=/tmp/php 413 | 414 | # PHP Build 415 | # https://github.com/php/php-src/releases 416 | # Needs: 417 | # - zlib 418 | # - libxml2 419 | # - openssl 420 | # - readline 421 | # - sodium 422 | RUN mkdir -p ${PHP_BUILD_DIR} 423 | WORKDIR ${PHP_BUILD_DIR} 424 | 425 | # Download and unpack the source code 426 | # --location will follow redirects 427 | # --silent will hide the progress, but also the errors: we restore error messages with --show-error 428 | # --fail makes sure that curl returns an error instead of fetching the 404 page 429 | ARG VERSION_PHP 430 | RUN curl --location --silent --show-error --fail https://www.php.net/get/php-${VERSION_PHP}.tar.gz/from/this/mirror \ 431 | | tar xzC . --strip-components=1 432 | 433 | # Configure the build 434 | # -fstack-protector-strong : Be paranoid about stack overflows 435 | # -fpic : Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64) 436 | # -fpie : Support Address Space Layout Randomization (see -fpic) 437 | # -O3 : Optimize for fastest binaries possible. 438 | # -I : Add the path to the list of directories to be searched for header files during preprocessing. 439 | # --enable-option-checking=fatal: make sure invalid --configure-flags are fatal errors instead of just warnings 440 | # --enable-ftp: because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236) 441 | # --enable-mbstring: because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195) 442 | ARG PHP_COMPILATION_FLAGS 443 | RUN ./buildconf --force 444 | RUN CFLAGS="-fstack-protector-strong -fpic -fpie -O3 -I${INSTALL_DIR}/include -I/usr/include -ffunction-sections -fdata-sections" \ 445 | CPPFLAGS="-fstack-protector-strong -fpic -fpie -O3 -I${INSTALL_DIR}/include -I/usr/include -ffunction-sections -fdata-sections" \ 446 | LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib -Wl,-O1 -Wl,--strip-all -Wl,--hash-style=both -pie" \ 447 | ./configure \ 448 | --prefix=${INSTALL_DIR} \ 449 | --enable-option-checking=fatal \ 450 | --enable-sockets \ 451 | --with-config-file-path=/opt/bref/etc/php \ 452 | --with-config-file-scan-dir=/opt/bref/etc/php/conf.d:/var/task/php/conf.d \ 453 | --enable-fpm \ 454 | --disable-cgi \ 455 | --enable-cli \ 456 | --disable-phpdbg \ 457 | --with-sodium \ 458 | --with-readline \ 459 | --with-openssl \ 460 | --with-zlib \ 461 | --with-curl \ 462 | --enable-exif \ 463 | --enable-ftp \ 464 | --with-gettext \ 465 | --enable-mbstring \ 466 | --with-pdo-mysql=shared,mysqlnd \ 467 | --with-mysqli \ 468 | --enable-pcntl \ 469 | --with-zip \ 470 | --enable-bcmath \ 471 | --with-pdo-pgsql=shared,${INSTALL_DIR} \ 472 | --enable-intl=shared \ 473 | --enable-soap \ 474 | --with-xsl=${INSTALL_DIR} \ 475 | --with-ffi \ 476 | # necessary for `pecl` to work (to install PHP extensions) 477 | --with-pear \ 478 | # extra compilation flags 479 | ${PHP_COMPILATION_FLAGS} 480 | RUN make -j $(nproc) 481 | # Run `make install` and override PEAR's PHAR URL because pear.php.net is down 482 | RUN set -xe; \ 483 | make install PEAR_INSTALLER_URL='https://github.com/pear/pearweb_phars/raw/master/install-pear-nozlib.phar'; \ 484 | { find ${INSTALL_DIR}/bin ${INSTALL_DIR}/sbin -type f -perm +0111 -exec strip --strip-all '{}' + || true; }; \ 485 | make clean; \ 486 | cp php.ini-production ${INSTALL_DIR}/etc/php/php.ini 487 | 488 | 489 | # Install extensions 490 | # We can install extensions manually or using `pecl` 491 | ENV VERSION_APCU=5.1.24 492 | RUN pecl install apcu-${VERSION_APCU} 493 | 494 | 495 | # --------------------------------------------------------------- 496 | # Now we copy everything we need for the layers into /bref-layer (which will be used for the real /opt later) 497 | RUN mkdir -p /bref-layer/bin \ 498 | && mkdir -p /bref-layer/lib \ 499 | && mkdir -p /bref-layer/bref/extensions \ 500 | && mkdir -p /bref-layer/bref/ssl 501 | 502 | # Copy the PHP binary 503 | RUN cp ${INSTALL_DIR}/bin/php /bref-layer/bin/php && chmod +x /bref-layer/bin/php 504 | 505 | # Copy all the external PHP extensions 506 | RUN cp $(php -r 'echo ini_get("extension_dir");')/* /bref-layer/bref/extensions/ 507 | 508 | # Copy all the required system libraries from: 509 | # - /lib | /lib64 (system libraries installed with `yum`) 510 | # - /opt/bin | /opt/lib | /opt/lib64 (libraries compiled from source) 511 | # into `/bref-layer` (the temp directory for the future Lambda layer) 512 | COPY --link utils/lib-copy /bref/lib-copy 513 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bin/php /bref-layer/lib 514 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/apcu.so /bref-layer/lib 515 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/intl.so /bref-layer/lib 516 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/opcache.so /bref-layer/lib 517 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/pdo_mysql.so /bref-layer/lib 518 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/pdo_pgsql.so /bref-layer/lib 519 | 520 | # Copy the OpenSSL certificates file 521 | RUN cp ${CA_BUNDLE} /bref-layer/bref/ssl/cert.pem 522 | 523 | # Copy the OpenSSL config 524 | RUN cp ${INSTALL_DIR}/bref/ssl/openssl.cnf /bref-layer/bref/ssl/openssl.cnf 525 | 526 | 527 | # --------------------------------------------------------------- 528 | # Start from a clean image to copy only the files we need 529 | FROM public.ecr.aws/lambda/provided:al2-${IMAGE_VERSION_SUFFIX} as isolation 530 | 531 | # We selected the files in /bref-layer, now we copy them to /opt (the real directory for the Lambda layer) 532 | COPY --link --from=build-environment /bref-layer /opt 533 | 534 | COPY --link layers/bootstrap.php /opt/bref/bootstrap.php 535 | 536 | 537 | FROM isolation as function 538 | 539 | COPY --link layers/function/bref.ini /opt/bref/etc/php/conf.d/ 540 | 541 | COPY --link layers/function/bootstrap.sh /opt/bootstrap 542 | # Copy files to /var/runtime to support deploying as a Docker image 543 | COPY --link layers/function/bootstrap.sh /var/runtime/bootstrap 544 | RUN chmod +x /opt/bootstrap && chmod +x /var/runtime/bootstrap 545 | 546 | 547 | # Up until here the entire file has been designed as a top-down reading/execution. 548 | # Everything necessary for the `function` layer has been installed, isolated and 549 | # packaged. Now we'll go back one step and start from the extensions so that we 550 | # can install fpm. Then we'll start the fpm layer and quickly isolate fpm. 551 | 552 | FROM build-environment as fpm-extension 553 | 554 | RUN cp ${INSTALL_DIR}/sbin/php-fpm /bref-layer/bin/php-fpm 555 | RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bin/php-fpm /bref-layer/lib 556 | 557 | 558 | FROM isolation as fpm 559 | 560 | COPY --link --from=fpm-extension /bref-layer /opt 561 | 562 | COPY --link layers/fpm/bref.ini /opt/bref/etc/php/conf.d/ 563 | 564 | COPY --link layers/fpm/bootstrap.sh /opt/bootstrap 565 | # Copy files to /var/runtime to support deploying as a Docker image 566 | COPY --link layers/fpm/bootstrap.sh /var/runtime/bootstrap 567 | RUN chmod +x /opt/bootstrap && chmod +x /var/runtime/bootstrap 568 | 569 | COPY --link layers/fpm/php-fpm.conf /opt/bref/etc/php-fpm.conf 570 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | composer.lock 3 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | export CPU_PREFIX ?= 2 | 3 | test: test-80 test-81 test-82 test-83 test-84 4 | 5 | # This rule matches with a wildcard, for example `test-80`. 6 | # The `$*` variable will contained the matched part, in this case `80`. 7 | test-%: vendor 8 | docker run --platform=${DOCKER_PLATFORM} --rm -v=$(PWD):/var/task:ro --entrypoint=php bref/${CPU_PREFIX}php-$* test_1_binary.php $* 9 | docker run --platform=${DOCKER_PLATFORM} --rm -v=$(PWD):/var/task:ro --entrypoint=php bref/${CPU_PREFIX}php-$*-fpm test_1_binary.php $* 10 | docker run --platform=${DOCKER_PLATFORM} --rm -v=$(PWD):/var/task:ro --entrypoint=php bref/${CPU_PREFIX}php-$*-fpm-dev test_1_binary.php $* 11 | 12 | docker run --platform=${DOCKER_PLATFORM} --rm -v=$(PWD):/var/task:ro --entrypoint=php bref/${CPU_PREFIX}php-$* test_2_extensions.php 13 | docker run --platform=${DOCKER_PLATFORM} --rm -v=$(PWD):/var/task:ro --entrypoint=php bref/${CPU_PREFIX}php-$*-fpm test_2_extensions.php 14 | docker run --platform=${DOCKER_PLATFORM} --rm -v=$(PWD):/var/task:ro --entrypoint=php bref/${CPU_PREFIX}php-$*-fpm-dev test_2_extensions.php 15 | 16 | docker run --platform=${DOCKER_PLATFORM} --rm -v=$(PWD):/var/task:ro --entrypoint=php \ 17 | -e PHP_INI_SCAN_DIR="/opt/bref/etc/php/conf.d/:/var/task/" bref/${CPU_PREFIX}php-$* \ 18 | test_3_manual_enabling_extensions.php 19 | 20 | # Test function handler 21 | docker stop test-${CPU_PREFIX}php-$* 2> /dev/null || true # silence errors 22 | docker run --platform=${DOCKER_PLATFORM} --rm --detach -v=$(PWD):/var/task:ro --name test-${CPU_PREFIX}php-$* \ 23 | bref/${CPU_PREFIX}php-$* test_4_function_handler.php 24 | docker exec test-${CPU_PREFIX}php-$* php test_4_function_invocation.php \ 25 | || (docker logs test-${CPU_PREFIX}php-$* && exit 1) 26 | docker stop test-${CPU_PREFIX}php-$* 27 | 28 | # Test FPM handler 29 | docker stop test-${CPU_PREFIX}php-$*-fpm 2> /dev/null || true # silence errors 30 | docker run --platform=${DOCKER_PLATFORM} --rm --detach -v=$(PWD):/var/task:ro --name test-${CPU_PREFIX}php-$*-fpm \ 31 | bref/${CPU_PREFIX}php-$*-fpm test_5_fpm_handler.php 32 | docker exec test-${CPU_PREFIX}php-$*-fpm php test_5_fpm_invocation.php \ 33 | || (docker logs test-${CPU_PREFIX}php-$*-fpm && exit 1) # print logs in case of failure 34 | docker stop test-${CPU_PREFIX}php-$*-fpm 35 | 36 | # Test console handler 37 | docker stop test-${CPU_PREFIX}php-$*-console 2> /dev/null || true # silence errors 38 | docker run --platform=${DOCKER_PLATFORM} --rm --detach -v=$(PWD):/var/task:ro --name test-${CPU_PREFIX}php-$*-console \ 39 | bref/${CPU_PREFIX}php-$*-console test_6_console_handler.php 40 | docker exec test-${CPU_PREFIX}php-$*-console php test_6_console_invocation.php \ 41 | || (docker logs test-${CPU_PREFIX}php-$*-console && exit 1) # print logs in case of failure 42 | docker stop test-${CPU_PREFIX}php-$*-console 43 | 44 | # Test that we can override PHP_INI_SCAN_DIR 45 | docker stop test-${CPU_PREFIX}php-$*-test7 2> /dev/null || true # silence errors 46 | docker run --platform=${DOCKER_PLATFORM} --rm --detach -v=$(PWD):/var/task:ro --name test-${CPU_PREFIX}php-$*-test7 \ 47 | -e PHP_INI_SCAN_DIR="/opt/bref/etc/php/conf.d/:/var/task/" \ 48 | bref/${CPU_PREFIX}php-$* test_4_function_handler.php 49 | docker exec test-${CPU_PREFIX}php-$*-test7 php test_7_custom_ini_scan_dir.php \ 50 | || (docker logs test-${CPU_PREFIX}php-$*-test7 && exit 1) # print logs in case of failure 51 | docker stop test-${CPU_PREFIX}php-$*-test7 52 | 53 | echo "\033[1;32m✓ Tests succeeded\033[0m" 54 | 55 | vendor: 56 | docker run --rm -v=$(PWD):/app composer install 57 | 58 | clean: 59 | rm -rf vendor composer.lock 60 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | This directory lets you test Lambda layers using Docker, either automatically or manually. 2 | 3 | **First, build the layers.** 4 | 5 | Then, run the automated tests: 6 | 7 | ```bash 8 | make test 9 | ``` 10 | 11 | To test the layers manually (for example to troubleshoot something), start the containers: 12 | 13 | ```bash 14 | make run 15 | ``` 16 | 17 | In another terminal, send test requests: 18 | 19 | ```bash 20 | make test-function 21 | make test-fpm 22 | ``` 23 | -------------------------------------------------------------------------------- /tests/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "bref/bref": "dev-master" 4 | }, 5 | "config": { 6 | "platform": { 7 | "php": "8.0.7" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/php/conf.d/test_4_php.ini: -------------------------------------------------------------------------------- 1 | memory_limit=586M 2 | -------------------------------------------------------------------------------- /tests/test_1_binary.php: -------------------------------------------------------------------------------- 1 | class_exists(\DateTime::class), 58 | 'filter_var' => filter_var('bref@bref.com', FILTER_VALIDATE_EMAIL), 59 | 'hash' => hash('md5', 'Bref') === 'df4647d91c4a054af655c8eea2bce541', 60 | 'libxml' => class_exists(\LibXMLError::class), 61 | 'openssl' => strlen(openssl_random_pseudo_bytes(1)) === 1, 62 | 'pntcl' => function_exists('pcntl_fork'), 63 | 'pcre' => preg_match('/abc/', 'abcde', $matches) && $matches[0] === 'abc', 64 | 'readline' => READLINE_LIB === 'readline', 65 | 'reflection' => class_exists(\ReflectionClass::class), 66 | 'session' => session_status() === PHP_SESSION_NONE, 67 | 'ffi' => class_exists(\FFI::class), 68 | 'zip' => class_exists(\ZipArchive::class), 69 | 'zlib' => md5(gzcompress('abcde')) === 'db245560922b42f1935e73e20b30980e', 70 | ]; 71 | foreach ($coreExtensions as $extension => $test) { 72 | if (! $test) { 73 | error($extension . ' core extension was not loaded'); 74 | } 75 | success("[Core extension] $extension"); 76 | } 77 | 78 | $extensions = [ 79 | 'curl' => function_exists('curl_init') 80 | // Make sure we are not using the default AL2 cURL version (7.79) 81 | && version_compare(curl_version()['version'], '7.84.0', '>='), 82 | // https://github.com/brefphp/aws-lambda-layers/issues/42 83 | 'curl-http2' => defined('CURL_HTTP_VERSION_2'), 84 | // Make sure we are not using the default AL2 OpenSSL version (7.79) 85 | 'curl-openssl' => str_starts_with(curl_version()['ssl_version'], 'OpenSSL/1.1.1') || str_starts_with(curl_version()['ssl_version'], 'OpenSSL/3'), 86 | // Check that the default certificate file exists 87 | // https://github.com/brefphp/aws-lambda-layers/issues/53 88 | 'curl-openssl-certificates' => file_exists(openssl_get_cert_locations()['default_cert_file']), 89 | // Check its location has not changed (would be a breaking change) 90 | 'curl-openssl-certificates-location' => openssl_get_cert_locations()['default_cert_file'] === '/opt/bref/ssl/cert.pem', 91 | // Make sure we are using curl with our compiled libssh 92 | 'curl-libssh' => version_compare(str_replace('libssh2/', '', curl_version()['libssh_version']), '1.10.0', '>='), 93 | 'openssl' => (function() { 94 | $private_key = openssl_pkey_new(['private_key_bits' => 2048]); 95 | if ($private_key === false) { 96 | return false; 97 | } 98 | 99 | $public_key_pem = openssl_pkey_get_details($private_key)['key']; 100 | $details = openssl_pkey_get_details(openssl_pkey_get_public($public_key_pem)); 101 | return $details['bits'] === 2048; 102 | })(), 103 | 'json' => function_exists('json_encode'), 104 | 'bcmath' => function_exists('bcadd'), 105 | 'ctype' => function_exists('ctype_digit'), 106 | 'dom' => class_exists(\DOMDocument::class), 107 | 'exif' => function_exists('exif_imagetype'), 108 | 'fileinfo' => function_exists('finfo_file'), 109 | 'ftp' => function_exists('ftp_connect'), 110 | 'gettext' => function_exists('gettext'), 111 | 'iconv' => function_exists('iconv_strlen'), 112 | 'mbstring' => function_exists('mb_strlen'), 113 | 'mysqli' => function_exists('mysqli_connect'), 114 | 'opcache' => ini_get('opcache.enable') == 1, 115 | 'pdo' => class_exists(\PDO::class), 116 | 'pdo_mysql' => extension_loaded('pdo_mysql'), 117 | 'pdo_sqlite' => extension_loaded('pdo_sqlite'), 118 | 'phar' => extension_loaded('phar'), 119 | 'posix' => function_exists('posix_getpgid'), 120 | 'simplexml' => class_exists(\SimpleXMLElement::class), 121 | 'sodium' => defined('PASSWORD_ARGON2I'), 122 | 'soap' => class_exists(\SoapClient::class), 123 | 'sockets' => function_exists('socket_connect'), 124 | 'spl' => class_exists(\SplQueue::class), 125 | 'sqlite3' => class_exists(\SQLite3::class), 126 | 'tokenizer' => function_exists('token_get_all'), 127 | 'libxml' => function_exists('libxml_get_errors'), 128 | 'xml' => function_exists('xml_parse'), 129 | 'xmlreader' => class_exists(\XMLReader::class), 130 | 'xmlwriter' => class_exists(\XMLWriter::class), 131 | 'xsl' => class_exists(\XSLTProcessor::class), 132 | ]; 133 | $errors = []; 134 | foreach ($extensions as $extension => $test) { 135 | if (! $test) { 136 | $errors[] = "[Extension] $extension extension was not loaded or failed the test"; 137 | } 138 | success("[Extension] $extension"); 139 | } 140 | if ($errors) { 141 | errors($errors); 142 | } 143 | 144 | $extensionsDisabledByDefault = [ 145 | 'intl' => class_exists(\Collator::class), 146 | 'apcu' => function_exists('apcu_add'), 147 | 'pdo_pgsql' => extension_loaded('pdo_pgsql'), 148 | ]; 149 | foreach ($extensionsDisabledByDefault as $extension => $test) { 150 | if ($test) { 151 | error($extension . ' extension was not supposed to be loaded'); 152 | } 153 | success("[Extension] $extension (disabled)"); 154 | } 155 | -------------------------------------------------------------------------------- /tests/test_3_manual_enabling_extensions.php: -------------------------------------------------------------------------------- 1 | class_exists(\Collator::class), 7 | 'apcu' => function_exists('apcu_add'), 8 | 'pdo_pgsql' => extension_loaded('pdo_pgsql'), 9 | ]; 10 | 11 | $extensionDir = ini_get('extension_dir'); 12 | if ($extensionDir !== '/opt/bref/extensions') { 13 | error("extension_dir points to $extensionDir instead of /opt/bref/extensions"); 14 | } 15 | success("[Extension] extension_dir points to /opt/bref/extensions"); 16 | 17 | foreach ($extensions as $extension => $test) { 18 | if (! $test) { 19 | error($extension . ' extension was not loaded'); 20 | } 21 | success("[Extension] $extension"); 22 | } 23 | -------------------------------------------------------------------------------- /tests/test_3_manual_extensions.ini: -------------------------------------------------------------------------------- 1 | extension=intl.so 2 | extension=apcu.so 3 | extension=pdo_pgsql.so 4 | -------------------------------------------------------------------------------- /tests/test_4_function_handler.php: -------------------------------------------------------------------------------- 1 | $event, 11 | 'server' => $_SERVER, 12 | 'memory_limit' => ini_get('memory_limit'), 13 | ]; 14 | }; 15 | -------------------------------------------------------------------------------- /tests/test_4_function_invocation.php: -------------------------------------------------------------------------------- 1 | 'From Bref!']; 29 | 30 | try { 31 | $response = post('http://127.0.0.1:8080/2015-03-31/functions/function/invocations', $body); 32 | $response = json_decode($response, true, 512, JSON_THROW_ON_ERROR); 33 | } catch (Throwable $e) { 34 | error($e->getMessage() . PHP_EOL . $e->getTraceAsString()); 35 | } 36 | 37 | if ($response['event']['Hello'] !== 'From Bref!') { 38 | error('Unexpected response: ' . json_encode($response)); 39 | } 40 | 41 | if ($response['memory_limit'] !== '586M') { 42 | error('Failed to load php.ini from /var/task/php/conf.d/'); 43 | } 44 | 45 | success('[Invoke] Function'); 46 | -------------------------------------------------------------------------------- /tests/test_5_event.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "routeKey": "$default", 4 | "rawPath": "/", 5 | "rawQueryString": "", 6 | "cookies": [], 7 | "headers": {}, 8 | "queryStringParameters": {}, 9 | "requestContext": { 10 | "accountId": "123456789012", 11 | "apiId": "api-id", 12 | "domainName": "id.execute-api.us-east-1.amazonaws.com", 13 | "domainPrefix": "id", 14 | "http": { 15 | "method": "POST", 16 | "path": "/", 17 | "protocol": "HTTP/1.1", 18 | "sourceIp": "IP", 19 | "userAgent": "agent" 20 | }, 21 | "requestId": "id", 22 | "routeKey": "$default", 23 | "stage": "$default", 24 | "time": "12/Mar/2020:19:03:58 +0000", 25 | "timeEpoch": 1583348638390 26 | }, 27 | "body": "Hello from Lambda", 28 | "pathParameters": {}, 29 | "isBase64Encoded": false, 30 | "stageVariables": {} 31 | } 32 | -------------------------------------------------------------------------------- /tests/test_5_fpm_handler.php: -------------------------------------------------------------------------------- 1 | getMessage() . PHP_EOL . $e->getTraceAsString()); 33 | } 34 | 35 | if ($response['body'] !== 'Hello from Bref FPM!') { 36 | error('Unexpected response: ' . json_encode($response)); 37 | } 38 | 39 | success('[Invoke] FPM'); 40 | -------------------------------------------------------------------------------- /tests/test_6_console_handler.php: -------------------------------------------------------------------------------- 1 | getMessage() . PHP_EOL . $e->getTraceAsString()); 35 | } 36 | 37 | if ($response['exitCode'] !== 0 || $response['output'] !== 'Hello From Bref!') { 38 | error('Unexpected response: ' . json_encode($response)); 39 | } 40 | 41 | success('[Invoke] Console'); 42 | -------------------------------------------------------------------------------- /tests/test_7_custom_ini_scan_dir.php: -------------------------------------------------------------------------------- 1 | getMessage() . PHP_EOL . $e->getTraceAsString()); 35 | } 36 | 37 | if (! is_array($response)) { 38 | error('The response is not an array'); 39 | } 40 | 41 | // We changed PHP_INI_SCAN_DIR to `/var/task` to load `test_3_manual_extensions.ini` 42 | // We check one of the extensions was indeed loaded 43 | if (! in_array('intl', $response, true)) { 44 | error('Could not override PHP_INI_SCAN_DIR, test_3_manual_extensions.ini was not loaded'); 45 | } 46 | 47 | success('[Invoke] Function'); 48 | -------------------------------------------------------------------------------- /tests/utils.php: -------------------------------------------------------------------------------- 1 | /dev/null || true 15 | 16 | docker create --name bref-export-zip "$IMAGE_NAME" 17 | 18 | docker cp bref-export-zip:/opt/. "output/$LAYER_NAME" 19 | 20 | cd "output/$LAYER_NAME" 21 | 22 | zip --quiet --recurse-paths "../$LAYER_NAME.zip" . 23 | 24 | docker rm -f bref-export-zip 25 | -------------------------------------------------------------------------------- /utils/lambda-publish/Makefile: -------------------------------------------------------------------------------- 1 | # This file is used to publish layers on multiple AWS regions in parallel. 2 | 3 | # Maximum number of parallel processes (default: 7) 4 | export MAX_PARALLEL_PUBLISH ?= 7 5 | 6 | # Set LAYER_NAME before calling this. 7 | publish-parallel: 8 | $(MAKE) -j${MAX_PARALLEL_PUBLISH} parallel-publish 9 | 10 | ########################################################################################## 11 | 12 | # This command is designed for parallel execution of layer publishing. 13 | # When we do `make publish -j7`, make will execute each command defined 14 | # here in parallel. 15 | parallel-publish: america-1 america-2 europe-1 europe-2 asia-1 asia-2 miscellaneous 16 | 17 | america-1: 18 | REGION=us-east-1 ./publish.sh #US East (N. Virginia) 19 | REGION=us-east-2 ./publish.sh #US East (Ohio) 20 | REGION=us-west-1 ./publish.sh #US West (N. California) 21 | 22 | america-2: 23 | REGION=us-west-2 ./publish.sh #US West (Oregon) 24 | REGION=ca-central-1 ./publish.sh #Canada (Central) 25 | REGION=sa-east-1 ./publish.sh #South America (São Paulo) 26 | 27 | europe-1: 28 | REGION=eu-west-1 ./publish.sh #Europe (Ireland) 29 | REGION=eu-west-2 ./publish.sh #Europe (London) 30 | REGION=eu-west-3 ./publish.sh #Europe (Paris) 31 | 32 | europe-2: 33 | REGION=eu-north-1 ./publish.sh #Europe (Stockholm) 34 | REGION=eu-south-1 ./publish.sh #Europe (Milan) 35 | REGION=eu-south-2 ./publish.sh #Europe (Spain) 36 | REGION=eu-central-1 ./publish.sh #Europe (Frankfurt) 37 | 38 | asia-1: 39 | REGION=ap-east-1 ./publish.sh #Asia Pacific (Hong Kong) 40 | REGION=ap-south-1 ./publish.sh #Asia Pacific (Mumbai) 41 | REGION=ap-southeast-1 ./publish.sh #Asia Pacific (Singapore) 42 | 43 | asia-2: 44 | REGION=ap-northeast-1 ./publish.sh #Asia Pacific (Tokyo) 45 | REGION=ap-northeast-3 ./publish.sh #Asia Pacific (Osaka) 46 | REGION=ap-northeast-2 ./publish.sh #Asia Pacific (Seoul) 47 | 48 | miscellaneous: 49 | REGION=af-south-1 ./publish.sh #Africa (Cape Town) 50 | REGION=me-south-1 ./publish.sh #Middle East (Bahrain) 51 | REGION=ap-southeast-2 ./publish.sh #Asia Pacific (Sydney) 52 | -------------------------------------------------------------------------------- /utils/lambda-publish/publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This file publishes a new AWS Lambda layer on AWS using the AWS CLI. 4 | # We rely on AWS CLI because it is installed by default on AWS CodeBuild. 5 | # 6 | # Environment variables: 7 | # - `LAYER_NAME`: **required** 8 | # - `REGION`: **required** Region to publish to. 9 | # - `ONLY_REGION`: If provided, only this region will be published 10 | 11 | # Fail on error 12 | set -e 13 | 14 | if [ -z "$LAYER_NAME" ]; then 15 | echo "\$LAYER_NAME must be set" 16 | exit 1 17 | fi 18 | if [ -z "$REGION" ]; then 19 | echo "\$REGION must be set" 20 | exit 1 21 | fi 22 | # If $ONLY_REGION is set and different from $REGION, then we skip this region 23 | if [ -n "$ONLY_REGION" ] && [ "$REGION" != "$ONLY_REGION" ]; then 24 | echo "Skipping $REGION" 25 | exit 0 26 | fi 27 | 28 | 29 | echo "[Publish] Publishing layer $LAYER_NAME to $REGION..." 30 | 31 | VERSION=$(aws lambda publish-layer-version \ 32 | --region $REGION \ 33 | --layer-name $LAYER_NAME \ 34 | --description "Bref PHP Runtime" \ 35 | --license-info MIT \ 36 | --zip-file fileb://../../output/$LAYER_NAME.zip \ 37 | --compatible-runtimes provided.al2 \ 38 | --output text \ 39 | --query Version) 40 | 41 | echo "[Publish] Layer $LAYER_NAME uploaded, adding permissions..." 42 | 43 | aws lambda add-layer-version-permission \ 44 | --region $REGION \ 45 | --layer-name $LAYER_NAME \ 46 | --version-number $VERSION \ 47 | --statement-id public \ 48 | --action lambda:GetLayerVersion \ 49 | --principal "*" 50 | 51 | echo "[Publish] Layer $LAYER_NAME published to $REGION" 52 | -------------------------------------------------------------------------------- /utils/lib-copy/Makefile: -------------------------------------------------------------------------------- 1 | # Update the list of system libs that exist by default in Lambda 2 | update: 3 | docker compose run --rm update-x86 4 | docker compose run --rm update-arm 5 | -------------------------------------------------------------------------------- /utils/lib-copy/copy-dependencies.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * For example: 11 | * php copy-dependencies.php /opt/bin/php /opt/lib 12 | * 13 | ********************************************************/ 14 | 15 | if (! ($argv[1] ?? false)) { 16 | echo 'Missing the first argument, check the file to see how to use it' . PHP_EOL; 17 | exit(1); 18 | } 19 | if (! ($argv[2] ?? false)) { 20 | echo 'Missing the second argument, check the file to see how to use it' . PHP_EOL; 21 | exit(1); 22 | } 23 | [$_, $pathToCheck, $targetDirectory] = $argv; 24 | 25 | // Create the target directory if it doesn't exist 26 | if (! is_dir($targetDirectory)) { 27 | mkdir($targetDirectory, 0777, true); 28 | } 29 | 30 | $arch = 'x86'; 31 | if (php_uname('m') !== 'x86_64') { 32 | $arch = 'arm'; 33 | } 34 | 35 | $librariesThatExistOnLambda = file(__DIR__ . "/libs-$arch.txt"); 36 | $librariesThatExistOnLambda = array_map('trim', $librariesThatExistOnLambda); 37 | // For some reason some libraries are actually not in Lambda, despite being in the docker image 🤷 38 | $librariesThatExistOnLambda = array_filter($librariesThatExistOnLambda, function ($library) { 39 | return ! str_contains($library, 'libgcrypt.so') 40 | && ! str_contains($library, 'libassuan.so') 41 | && ! str_contains($library, 'libgobject-2.0.so') 42 | && ! str_contains($library, 'libgpg-error.so') 43 | && ! str_contains($library, 'libgpgme-pthread.so') 44 | && ! str_contains($library, 'libgpgme.so') 45 | ; 46 | }); 47 | 48 | $requiredLibraries = listDependencies($pathToCheck); 49 | // Exclude existing system libraries 50 | $requiredLibraries = array_filter($requiredLibraries, function (string $lib) use ($librariesThatExistOnLambda) { 51 | // Libraries that we compiled are in /opt/lib or /opt/lib64, we compiled them because they are more 52 | // recent than the ones in Lambda so we definitely want to use them 53 | $isALibraryWeCompiled = str_starts_with($lib, '/opt/lib'); 54 | $doesNotExistInLambda = !in_array(basename($lib), $librariesThatExistOnLambda, true); 55 | $keep = $isALibraryWeCompiled || $doesNotExistInLambda; 56 | if (! $keep) { 57 | echo "Skipping $lib because it's already in Lambda" . PHP_EOL; 58 | } 59 | return $keep; 60 | }); 61 | 62 | // Copy all the libraries 63 | foreach ($requiredLibraries as $libraryPath) { 64 | $targetPath = $targetDirectory . '/' . basename($libraryPath); 65 | echo "Copying $libraryPath to $targetPath" . PHP_EOL; 66 | $success = copy($libraryPath, $targetPath); 67 | if (! $success) { 68 | throw new RuntimeException("Could not copy $libraryPath to $targetPath"); 69 | } 70 | } 71 | 72 | 73 | function listDependencies(string $path): array 74 | { 75 | // ldd lists the dependencies of a binary or library/extension (.so file) 76 | exec("ldd $path 2>&1", $lines); 77 | if (str_contains(end($lines), 'exited with unknown exit code (139)')) { 78 | // We can't use `ldd` on binaries (like /opt/bin/php) because it fails on cross-platform builds 79 | // so we fall back to `LD_TRACE_LOADED_OBJECTS` (which doesn't work for .so files, that's why we also try `ldd`) 80 | // See https://stackoverflow.com/a/35905007/245552 81 | $output = shell_exec("LD_TRACE_LOADED_OBJECTS=1 $path 2>&1"); 82 | if (!$output) { 83 | throw new RuntimeException("Could not list dependencies for $path"); 84 | } 85 | $lines = explode(PHP_EOL, $output); 86 | } 87 | $dependencies = []; 88 | foreach ($lines as $line) { 89 | if (str_ends_with($line, ' => not found')) { 90 | throw new RuntimeException("This library is a dependency for $path but cannot be found by 'ldd':\n$line\n"); 91 | } 92 | $matches = []; 93 | if (preg_match('/=> (.*) \(0x[0-9a-f]+\)/', $line, $matches)) { 94 | $dependencies[] = $matches[1]; 95 | } 96 | } 97 | return $dependencies; 98 | } 99 | -------------------------------------------------------------------------------- /utils/lib-copy/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | 5 | # List all files from `/lib64` into `libs-x86.txt` 6 | update-x86: 7 | image: public.ecr.aws/lambda/provided:al2-x86_64 8 | entrypoint: /bin/sh 9 | command: [ "-c", "find /lib64/ -maxdepth 1 -not -type d -printf '%f\n' | sort > /libs-x86.txt" ] 10 | # Alternative approach from https://gist.github.com/vladgolubev/439559fc7597a4fb51eaa9e97b72f319 11 | # but it seems to list less files, so I'm not sure we should use that alternative 12 | # command: [ "-c", "/sbin/ldconfig -p | awk '{print $$1}' | sort > /al2-x64.txt" ] 13 | volumes: 14 | - ./libs-x86.txt:/libs-x86.txt 15 | 16 | # List all files from `/lib64` into `libs-arm.txt` 17 | update-arm: 18 | image: public.ecr.aws/lambda/provided:al2-arm64 19 | entrypoint: /bin/sh 20 | command: [ "-c", "find /lib64/ -maxdepth 1 -not -type d -printf '%f\n' | sort > /libs-arm.txt" ] 21 | volumes: 22 | - ./libs-arm.txt:/libs-arm.txt 23 | -------------------------------------------------------------------------------- /utils/lib-copy/libs-arm.txt: -------------------------------------------------------------------------------- 1 | ld-2.26.so 2 | ld-linux-aarch64.so.1 3 | libacl.so.1 4 | libacl.so.1.1.0 5 | libanl-2.26.so 6 | libanl.so.1 7 | libassuan.so.0 8 | libassuan.so.0.4.0 9 | libattr.so.1 10 | libattr.so.1.1.0 11 | libblkid.so.1 12 | libblkid.so.1.1.0 13 | libBrokenLocale-2.26.so 14 | libBrokenLocale.so.1 15 | libbz2.so.1 16 | libbz2.so.1.0.6 17 | libc-2.26.so 18 | libcap.so.2 19 | libcap.so.2.54 20 | libcidn-2.26.so 21 | libcidn.so.1 22 | libcom_err.so.2 23 | libcom_err.so.2.1 24 | libcrypt-2.26.so 25 | libcrypto.so.10 26 | libcrypto.so.1.0.2k 27 | .libcrypto.so.1.0.2k.hmac 28 | .libcrypto.so.10.hmac 29 | libcrypt.so.1 30 | libc.so.6 31 | libcurl.so.4 32 | libcurl.so.4.8.0 33 | libdb-5.3.so 34 | libdb-5.so 35 | libdl-2.26.so 36 | libdl.so.2 37 | libelf-0.176.so 38 | libelf.so.1 39 | libexpat.so.1 40 | libexpat.so.1.6.0 41 | libffi.so.6 42 | libffi.so.6.0.1 43 | libfontconfig.so.1 44 | libfontconfig.so.1.11.1 45 | libform.so.6 46 | libform.so.6.0 47 | libformw.so.6 48 | libformw.so.6.0 49 | libfreebl3.chk 50 | libfreebl3.so 51 | libfreeblpriv3.chk 52 | libfreeblpriv3.so 53 | libfreetype.so.6 54 | libfreetype.so.6.14.0 55 | libgcc_s-7-20180712.so.1 56 | libgcc_s.so.1 57 | libgcrypt.so.11 58 | libgcrypt.so.11.8.2 59 | .libgcrypt.so.11.hmac 60 | libgdbm_compat.so.4 61 | libgdbm_compat.so.4.0.0 62 | libgdbm.so.4 63 | libgdbm.so.4.0.0 64 | libgio-2.0.so.0 65 | libgio-2.0.so.0.5600.1 66 | libglib-2.0.so.0 67 | libglib-2.0.so.0.5600.1 68 | libgmodule-2.0.so.0 69 | libgmodule-2.0.so.0.5600.1 70 | libgmp.so.10 71 | libgmp.so.10.2.0 72 | libgmpxx.so.4 73 | libgmpxx.so.4.4.0 74 | libgobject-2.0.so.0 75 | libgobject-2.0.so.0.5600.1 76 | libgpg-error.so.0 77 | libgpg-error.so.0.10.0 78 | libgpgme-pthread.so.11 79 | libgpgme-pthread.so.11.8.1 80 | libgpgme.so.11 81 | libgpgme.so.11.8.1 82 | libgssapi_krb5.so.2 83 | libgssapi_krb5.so.2.2 84 | libgssrpc.so.4 85 | libgssrpc.so.4.2 86 | libgthread-2.0.so.0 87 | libgthread-2.0.so.0.5600.1 88 | libhistory.so.6 89 | libhistory.so.6.2 90 | libicudata.so.50 91 | libicudata.so.50.2 92 | libicui18n.so.50 93 | libicui18n.so.50.2 94 | libicuio.so.50 95 | libicuio.so.50.2 96 | libicule.so.50 97 | libicule.so.50.2 98 | libiculx.so.50 99 | libiculx.so.50.2 100 | libicutest.so.50 101 | libicutest.so.50.2 102 | libicutu.so.50 103 | libicutu.so.50.2 104 | libicuuc.so.50 105 | libicuuc.so.50.2 106 | libidn2.so.0 107 | libidn2.so.0.3.7 108 | libk5crypto.so.3 109 | libk5crypto.so.3.1 110 | libkdb5.so.8 111 | libkdb5.so.8.0 112 | libkeyutils.so.1 113 | libkeyutils.so.1.5 114 | libkrad.so.0 115 | libkrad.so.0.0 116 | libkrb5.so.3 117 | libkrb5.so.3.3 118 | libkrb5support.so.0 119 | libkrb5support.so.0.1 120 | liblber-2.4.so.2 121 | liblber-2.4.so.2.10.7 122 | libldap-2.4.so.2 123 | libldap-2.4.so.2.10.7 124 | libldap_r-2.4.so.2 125 | libldap_r-2.4.so.2.10.7 126 | liblua-5.1.so 127 | liblzma.so.5 128 | liblzma.so.5.2.2 129 | libm-2.26.so 130 | libmagic.so.1 131 | libmagic.so.1.0.0 132 | libmemusage.so 133 | libmenu.so.6 134 | libmenu.so.6.0 135 | libmenuw.so.6 136 | libmenuw.so.6.0 137 | libmount.so.1 138 | libmount.so.1.1.0 139 | libm.so.6 140 | libncurses.so.6 141 | libncurses.so.6.0 142 | libncursesw.so.6 143 | libncursesw.so.6.0 144 | libnghttp2.so.14 145 | libnghttp2.so.14.20.0 146 | libnsl-2.26.so 147 | libnsl.so.1 148 | libnspr4.so 149 | libnss3.so 150 | libnssckbi.so 151 | libnss_compat-2.26.so 152 | libnss_compat.so.2 153 | libnssdbm3.chk 154 | libnssdbm3.so 155 | libnss_dns-2.26.so 156 | libnss_dns.so.2 157 | libnss_files-2.26.so 158 | libnss_files.so.2 159 | libnsspem.so 160 | libnsssysinit.so 161 | libnssutil3.so 162 | libp11-kit.so.0 163 | libp11-kit.so.0.3.0 164 | libpanel.so.6 165 | libpanel.so.6.0 166 | libpanelw.so.6 167 | libpanelw.so.6.0 168 | libpcprofile.so 169 | libpcre16.so.0 170 | libpcre16.so.0.2.0 171 | libpcre32.so.0 172 | libpcre32.so.0.0.0 173 | libpcrecpp.so.0 174 | libpcrecpp.so.0.0.0 175 | libpcreposix.so.0 176 | libpcreposix.so.0.0.1 177 | libpcre.so.1 178 | libpcre.so.1.2.0 179 | libplc4.so 180 | libplds4.so 181 | libpng15.so.15 182 | libpng15.so.15.13.0 183 | libpopt.so.0 184 | libpopt.so.0.0.0 185 | libpsl.so.5 186 | libpsl.so.5.3.5 187 | libpsx.so.2 188 | libpsx.so.2.54 189 | libpthread-2.26.so 190 | libpthread.so.0 191 | libpth.so.20 192 | libpth.so.20.0.27 193 | libpython2.7.so.1.0 194 | libreadline.so.6 195 | libreadline.so.6.2 196 | libresolv-2.26.so 197 | libresolv.so.2 198 | librpmbuild.so.3 199 | librpmbuild.so.3.2.2 200 | librpmio.so.3 201 | librpmio.so.3.2.2 202 | librpmsign.so.1 203 | librpmsign.so.1.2.2 204 | librpm.so.3 205 | librpm.so.3.2.2 206 | librt-2.26.so 207 | librt.so.1 208 | libsasl2.so.3 209 | libsasl2.so.3.0.0 210 | libSegFault.so 211 | libselinux.so.1 212 | libsepol.so.1 213 | libslapi-2.4.so.2 214 | libslapi-2.4.so.2.10.7 215 | libsmime3.so 216 | libsoftokn3.chk 217 | libsoftokn3.so 218 | libsqlite3.so.0 219 | libsqlite3.so.0.8.6 220 | libssh2.so.1 221 | libssh2.so.1.0.1 222 | libssl3.so 223 | libssl.so.10 224 | libssl.so.1.0.2k 225 | .libssl.so.1.0.2k.hmac 226 | .libssl.so.10.hmac 227 | libstdc++.so.6 228 | libstdc++.so.6.0.24 229 | libtasn1.so.6 230 | libtasn1.so.6.5.3 231 | libthread_db-1.0.so 232 | libthread_db.so.1 233 | libtic.so.6 234 | libtic.so.6.0 235 | libtinfo.so.6 236 | libtinfo.so.6.0 237 | libunistring.so.0 238 | libunistring.so.0.1.2 239 | libutil-2.26.so 240 | libutil.so.1 241 | libuuid.so.1 242 | libuuid.so.1.3.0 243 | libverto.so.1 244 | libverto.so.1.0.0 245 | libxml2.so.2 246 | libxml2.so.2.9.1 247 | libz.so.1 248 | libz.so.1.2.7 249 | p11-kit-proxy.so 250 | p11-kit-trust.so 251 | -------------------------------------------------------------------------------- /utils/lib-copy/libs-x86.txt: -------------------------------------------------------------------------------- 1 | ld-2.26.so 2 | ld-linux-x86-64.so.2 3 | libacl.so.1 4 | libacl.so.1.1.0 5 | libanl-2.26.so 6 | libanl.so.1 7 | libassuan.so.0 8 | libassuan.so.0.4.0 9 | libattr.so.1 10 | libattr.so.1.1.0 11 | libblkid.so.1 12 | libblkid.so.1.1.0 13 | libBrokenLocale-2.26.so 14 | libBrokenLocale.so.1 15 | libbz2.so.1 16 | libbz2.so.1.0.6 17 | libc-2.26.so 18 | libcap.so.2 19 | libcap.so.2.54 20 | libcidn-2.26.so 21 | libcidn.so.1 22 | libcom_err.so.2 23 | libcom_err.so.2.1 24 | libcrypt-2.26.so 25 | libcrypto.so.10 26 | libcrypto.so.1.0.2k 27 | .libcrypto.so.1.0.2k.hmac 28 | .libcrypto.so.10.hmac 29 | libcrypt.so.1 30 | libc.so.6 31 | libcurl.so.4 32 | libcurl.so.4.8.0 33 | libdb-5.3.so 34 | libdb-5.so 35 | libdl-2.26.so 36 | libdl.so.2 37 | libelf-0.176.so 38 | libelf.so.1 39 | libexpat.so.1 40 | libexpat.so.1.6.0 41 | libffi.so.6 42 | libffi.so.6.0.1 43 | libfontconfig.so.1 44 | libfontconfig.so.1.11.1 45 | libform.so.6 46 | libform.so.6.0 47 | libformw.so.6 48 | libformw.so.6.0 49 | libfreebl3.chk 50 | libfreebl3.so 51 | libfreeblpriv3.chk 52 | libfreeblpriv3.so 53 | libfreetype.so.6 54 | libfreetype.so.6.14.0 55 | libgcc_s-7-20180712.so.1 56 | libgcc_s.so.1 57 | libgcrypt.so.11 58 | libgcrypt.so.11.8.2 59 | .libgcrypt.so.11.hmac 60 | libgdbm_compat.so.4 61 | libgdbm_compat.so.4.0.0 62 | libgdbm.so.4 63 | libgdbm.so.4.0.0 64 | libgio-2.0.so.0 65 | libgio-2.0.so.0.5600.1 66 | libglib-2.0.so.0 67 | libglib-2.0.so.0.5600.1 68 | libgmodule-2.0.so.0 69 | libgmodule-2.0.so.0.5600.1 70 | libgmp.so.10 71 | libgmp.so.10.2.0 72 | libgmpxx.so.4 73 | libgmpxx.so.4.4.0 74 | libgobject-2.0.so.0 75 | libgobject-2.0.so.0.5600.1 76 | libgpg-error.so.0 77 | libgpg-error.so.0.10.0 78 | libgpgme-pthread.so.11 79 | libgpgme-pthread.so.11.8.1 80 | libgpgme.so.11 81 | libgpgme.so.11.8.1 82 | libgssapi_krb5.so.2 83 | libgssapi_krb5.so.2.2 84 | libgssrpc.so.4 85 | libgssrpc.so.4.2 86 | libgthread-2.0.so.0 87 | libgthread-2.0.so.0.5600.1 88 | libhistory.so.6 89 | libhistory.so.6.2 90 | libicudata.so.50 91 | libicudata.so.50.2 92 | libicui18n.so.50 93 | libicui18n.so.50.2 94 | libicuio.so.50 95 | libicuio.so.50.2 96 | libicule.so.50 97 | libicule.so.50.2 98 | libiculx.so.50 99 | libiculx.so.50.2 100 | libicutest.so.50 101 | libicutest.so.50.2 102 | libicutu.so.50 103 | libicutu.so.50.2 104 | libicuuc.so.50 105 | libicuuc.so.50.2 106 | libidn2.so.0 107 | libidn2.so.0.3.7 108 | libk5crypto.so.3 109 | libk5crypto.so.3.1 110 | libkdb5.so.8 111 | libkdb5.so.8.0 112 | libkeyutils.so.1 113 | libkeyutils.so.1.5 114 | libkrad.so.0 115 | libkrad.so.0.0 116 | libkrb5.so.3 117 | libkrb5.so.3.3 118 | libkrb5support.so.0 119 | libkrb5support.so.0.1 120 | liblber-2.4.so.2 121 | liblber-2.4.so.2.10.7 122 | libldap-2.4.so.2 123 | libldap-2.4.so.2.10.7 124 | libldap_r-2.4.so.2 125 | libldap_r-2.4.so.2.10.7 126 | liblua-5.1.so 127 | liblzma.so.5 128 | liblzma.so.5.2.2 129 | libm-2.26.so 130 | libmagic.so.1 131 | libmagic.so.1.0.0 132 | libmemusage.so 133 | libmenu.so.6 134 | libmenu.so.6.0 135 | libmenuw.so.6 136 | libmenuw.so.6.0 137 | libmount.so.1 138 | libmount.so.1.1.0 139 | libm.so.6 140 | libmvec-2.26.so 141 | libmvec.so.1 142 | libncurses.so.6 143 | libncurses.so.6.0 144 | libncursesw.so.6 145 | libncursesw.so.6.0 146 | libnghttp2.so.14 147 | libnghttp2.so.14.20.0 148 | libnsl-2.26.so 149 | libnsl.so.1 150 | libnspr4.so 151 | libnss3.so 152 | libnssckbi.so 153 | libnss_compat-2.26.so 154 | libnss_compat.so.2 155 | libnssdbm3.chk 156 | libnssdbm3.so 157 | libnss_dns-2.26.so 158 | libnss_dns.so.2 159 | libnss_files-2.26.so 160 | libnss_files.so.2 161 | libnsspem.so 162 | libnsssysinit.so 163 | libnssutil3.so 164 | libp11-kit.so.0 165 | libp11-kit.so.0.3.0 166 | libpanel.so.6 167 | libpanel.so.6.0 168 | libpanelw.so.6 169 | libpanelw.so.6.0 170 | libpcprofile.so 171 | libpcre16.so.0 172 | libpcre16.so.0.2.0 173 | libpcre32.so.0 174 | libpcre32.so.0.0.0 175 | libpcrecpp.so.0 176 | libpcrecpp.so.0.0.0 177 | libpcreposix.so.0 178 | libpcreposix.so.0.0.1 179 | libpcre.so.1 180 | libpcre.so.1.2.0 181 | libplc4.so 182 | libplds4.so 183 | libpng15.so.15 184 | libpng15.so.15.13.0 185 | libpopt.so.0 186 | libpopt.so.0.0.0 187 | libpsl.so.5 188 | libpsl.so.5.3.5 189 | libpsx.so.2 190 | libpsx.so.2.54 191 | libpthread-2.26.so 192 | libpthread.so.0 193 | libpth.so.20 194 | libpth.so.20.0.27 195 | libpython2.7.so.1.0 196 | libreadline.so.6 197 | libreadline.so.6.2 198 | libresolv-2.26.so 199 | libresolv.so.2 200 | librpmbuild.so.3 201 | librpmbuild.so.3.2.2 202 | librpmio.so.3 203 | librpmio.so.3.2.2 204 | librpmsign.so.1 205 | librpmsign.so.1.2.2 206 | librpm.so.3 207 | librpm.so.3.2.2 208 | librt-2.26.so 209 | librt.so.1 210 | libsasl2.so.3 211 | libsasl2.so.3.0.0 212 | libSegFault.so 213 | libselinux.so.1 214 | libsepol.so.1 215 | libslapi-2.4.so.2 216 | libslapi-2.4.so.2.10.7 217 | libsmime3.so 218 | libsoftokn3.chk 219 | libsoftokn3.so 220 | libsqlite3.so.0 221 | libsqlite3.so.0.8.6 222 | libssh2.so.1 223 | libssh2.so.1.0.1 224 | libssl3.so 225 | libssl.so.10 226 | libssl.so.1.0.2k 227 | .libssl.so.1.0.2k.hmac 228 | .libssl.so.10.hmac 229 | libstdc++.so.6 230 | libstdc++.so.6.0.24 231 | libtasn1.so.6 232 | libtasn1.so.6.5.3 233 | libthread_db-1.0.so 234 | libthread_db.so.1 235 | libtic.so.6 236 | libtic.so.6.0 237 | libtinfo.so.6 238 | libtinfo.so.6.0 239 | libunistring.so.0 240 | libunistring.so.0.1.2 241 | libutil-2.26.so 242 | libutil.so.1 243 | libuuid.so.1 244 | libuuid.so.1.3.0 245 | libverto.so.1 246 | libverto.so.1.0.0 247 | libxml2.so.2 248 | libxml2.so.2.9.1 249 | libz.so.1 250 | libz.so.1.2.7 251 | p11-kit-proxy.so 252 | p11-kit-trust.so 253 | --------------------------------------------------------------------------------