Skip to content

Commit 87eefb3

Browse files
authored
Merge pull request #282 from brefphp/php-85
Add support for PHP 8.5 in Bref v3
2 parents 793a053 + 1f12d19 commit 87eefb3

File tree

5 files changed

+332
-8
lines changed

5 files changed

+332
-8
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
script: |
2626
const matrix = {
2727
cpu: ['x86', 'arm'],
28-
php_version: ['82', '83', '84'],
28+
php_version: ['82', '83', '84', '85'],
2929
}
3030
3131
// If this is a third-party pull request, skip ARM builds

Makefile

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ default: docker-images layers
3535

3636

3737
# Build Docker images *locally*
38-
docker-images: docker-images-php-82 docker-images-php-83 docker-images-php-84
38+
docker-images: docker-images-php-82 docker-images-php-83 docker-images-php-84 docker-images-php-85
3939
docker-images-php-%:
4040
PHP_VERSION=$* ${BAKE_COMMAND} --load
4141

4242

4343
# Build Lambda layers (zip files) *locally*
44-
layers: layer-php-82 layer-php-83 layer-php-84
44+
layers: layer-php-82 layer-php-83 layer-php-84 layer-php-85
4545
# This rule matches with a wildcard, for example `layer-php-84`.
4646
# The `$*` variable will contained the matched part, in this case `php-84`.
4747
layer-%:
@@ -51,13 +51,13 @@ layer-%:
5151
# Upload the layers to AWS Lambda
5252
# Uses the current AWS_PROFILE. Most users will not want to use this option
5353
# as this will publish all layers to all regions + publish all Docker images.
54-
upload-layers: upload-layers-php-82 upload-layers-php-83 upload-layers-php-84
54+
upload-layers: upload-layers-php-82 upload-layers-php-83 upload-layers-php-84 upload-layers-php-85
5555
upload-layers-php-%:
5656
LAYER_NAME=${CPU_PREFIX}php-$* $(MAKE) -C ./utils/lambda-publish publish-parallel
5757

5858

5959
# Publish Docker images to Docker Hub.
60-
upload-to-docker-hub: upload-to-docker-hub-php-82 upload-to-docker-hub-php-83 upload-to-docker-hub-php-84
60+
upload-to-docker-hub: upload-to-docker-hub-php-82 upload-to-docker-hub-php-83 upload-to-docker-hub-php-84 upload-to-docker-hub-php-85
6161
upload-to-docker-hub-php-%:
6262
# Make sure we have defined the docker tag
6363
(test $(DOCKER_TAG)) && echo "Tagging images with \"${DOCKER_TAG}\"" || echo "You have to define environment variable DOCKER_TAG"
@@ -74,12 +74,12 @@ upload-to-docker-hub-php-%:
7474
done
7575

7676

77-
test: test-82 test-83 test-84
77+
test: test-82 test-83 test-84 test-85
7878
test-%:
7979
cd tests && $(MAKE) test-$*
8080

8181

82-
clean: clean-82 clean-83 clean-84
82+
clean: clean-82 clean-83 clean-84 clean-85
8383
# Clear the build cache, else all images will be rebuilt using cached layers
8484
docker builder prune
8585
# Remove zip files

php-85/Dockerfile

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
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.5.0beta1
8+
9+
10+
# Lambda uses a custom AMI named Amazon Linux 2023
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:al2023-${IMAGE_VERSION_SUFFIX} as build-environment
15+
16+
17+
RUN set -xe \
18+
# Download dnf repository data to cache
19+
&& dnf makecache \
20+
# Install default development tools (gcc, make, etc)
21+
&& dnf install -y make gcc gcc-c++ autoconf automake libtool
22+
23+
24+
# We need a base path for all the sourcecode we will build from.
25+
ENV BUILD_DIR="/tmp/build"
26+
27+
# Target installation path for all the binaries and libraries we will compile.
28+
# We need to use /opt because that's where AWS Lambda layers are unzipped,
29+
# and we need binaries (e.g. /opt/bin/php) to look for libraries in /opt/lib.
30+
# Indeed, `/opt/lib` is a path Lambda looks for libraries by default (it is in `LD_LIBRARY_PATH`)
31+
# AND the `/opt/lib` path will be hardcoded in the compiled binaries and libraries (called "rpath").
32+
#
33+
# Note: the /opt directory will be completely recreated from scratch in the final images,
34+
# so it's ok at this stage if we "pollute" it with plenty of extra libs/build artifacts.
35+
ENV INSTALL_DIR="/opt"
36+
37+
# We need some default compiler variables setup
38+
ENV PKG_CONFIG_PATH="${INSTALL_DIR}/lib64/pkgconfig:${INSTALL_DIR}/lib/pkgconfig" \
39+
PKG_CONFIG="/usr/bin/pkg-config" \
40+
PATH="${INSTALL_DIR}/bin:${PATH}"
41+
42+
ENV LD_LIBRARY_PATH="${INSTALL_DIR}/lib64:${INSTALL_DIR}/lib"
43+
44+
# Enable parallelism by default for make and cmake (like make -j)
45+
# See https://stackoverflow.com/a/50883540/245552
46+
ENV CMAKE_BUILD_PARALLEL_LEVEL=4
47+
ENV MAKEFLAGS='-j4'
48+
49+
# Ensure we have all the directories we require in the container.
50+
RUN mkdir -p ${BUILD_DIR} \
51+
${INSTALL_DIR}/bin \
52+
${INSTALL_DIR}/doc \
53+
${INSTALL_DIR}/etc/php \
54+
${INSTALL_DIR}/etc/php/conf.d \
55+
${INSTALL_DIR}/include \
56+
${INSTALL_DIR}/lib \
57+
${INSTALL_DIR}/lib64 \
58+
${INSTALL_DIR}/libexec \
59+
${INSTALL_DIR}/sbin \
60+
${INSTALL_DIR}/share
61+
62+
63+
###############################################################################
64+
# SQLite
65+
# Since PHP 7.4, libsqlite must be installed (https://github.com/php/php-src/blob/99b8e67615159fc600a615e1e97f2d1cf18f14cb/UPGRADING#L616-L619)
66+
# Laravel 11 requires SQLite 3.35+ https://laravel.com/docs/11.x/upgrade#sqlite-minimum-version
67+
# Drupal 11 requires SQLite 3.45+ https://www.drupal.org/docs/getting-started/system-requirements/database-server-requirements
68+
# The AL2023 built-in version is 3.40.0, so we compile a newer version.
69+
# https://www.sqlite.org/changes.html
70+
# Needed by:
71+
# - php
72+
RUN LD_LIBRARY_PATH= dnf install -y tcl
73+
ENV VERSION_SQLITE=3.50.4
74+
ENV SQLITE_BUILD_DIR=${BUILD_DIR}/sqlite
75+
RUN set -xe; \
76+
mkdir -p ${SQLITE_BUILD_DIR}; \
77+
curl -Ls https://github.com/sqlite/sqlite/archive/refs/tags/version-${VERSION_SQLITE}.tar.gz \
78+
| tar xzC ${SQLITE_BUILD_DIR} --strip-components=1
79+
WORKDIR ${SQLITE_BUILD_DIR}
80+
RUN CFLAGS="-Os" CPPFLAGS="-Os" ./configure --prefix=${INSTALL_DIR}
81+
RUN make && make install
82+
83+
84+
###############################################################################
85+
# Install some dev files for using old libraries already on the system
86+
# libcurl-devel : needed for the curl extension
87+
# zlib-devel : needed for zlib/gz in PHP
88+
# readline-devel : needed for the readline extension
89+
# gettext-devel : needed for the --with-gettext flag
90+
# libicu-devel : needed for intl
91+
# libxslt-devel : needed for the XSL extension
92+
# libsodium-devel : needed for the sodium extension
93+
# libffi-devel : needed for the FFI extension
94+
RUN LD_LIBRARY_PATH= dnf install -y libcurl-devel zlib-devel readline-devel gettext-devel libicu-devel libxslt-devel libzip-devel oniguruma-devel libpq-devel openssl-devel libsodium-devel libffi-devel
95+
96+
97+
# Note: this variable is used when building extra/custom extensions, do not remove
98+
ENV PHP_BUILD_DIR=/tmp/php
99+
100+
# PHP Build
101+
# https://github.com/php/php-src/releases
102+
# Needs:
103+
# - zlib
104+
# - libxml2
105+
# - openssl
106+
# - readline
107+
# - sodium
108+
RUN mkdir -p ${PHP_BUILD_DIR}
109+
WORKDIR ${PHP_BUILD_DIR}
110+
111+
# Download and unpack the source code
112+
# --location will follow redirects
113+
# --silent will hide the progress, but also the errors: we restore error messages with --show-error
114+
# --fail makes sure that curl returns an error instead of fetching the 404 page
115+
ARG VERSION_PHP
116+
RUN curl --location --silent --show-error --fail https://downloads.php.net/~edorian/php-${VERSION_PHP}.tar.gz \
117+
| tar xzC . --strip-components=1
118+
119+
# Configure the build
120+
# -fstack-protector-strong : Be paranoid about stack overflows
121+
# -fpic : Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
122+
# -fpie : Support Address Space Layout Randomization (see -fpic)
123+
# -O3 : Optimize for fastest binaries possible.
124+
# -I : Add the path to the list of directories to be searched for header files during preprocessing.
125+
# --enable-option-checking=fatal: make sure invalid --configure-flags are fatal errors instead of just warnings
126+
# --enable-ftp: because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
127+
# --enable-mbstring: because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
128+
# --with-zlib: See https://stackoverflow.com/a/42978649/245552
129+
ARG PHP_COMPILATION_FLAGS
130+
RUN ./buildconf --force
131+
RUN CFLAGS="-fstack-protector-strong -fpic -fpie -Os -I${INSTALL_DIR}/include -I/usr/include -ffunction-sections -fdata-sections" \
132+
CPPFLAGS="-fstack-protector-strong -fpic -fpie -Os -I${INSTALL_DIR}/include -I/usr/include -ffunction-sections -fdata-sections" \
133+
LDFLAGS="-L${INSTALL_DIR}/lib64 -L${INSTALL_DIR}/lib -Wl,-O1 -Wl,--strip-all -Wl,--hash-style=both -pie" \
134+
./configure \
135+
--prefix=${INSTALL_DIR} \
136+
--enable-option-checking=fatal \
137+
--enable-sockets \
138+
--with-config-file-path=/opt/bref/etc/php \
139+
--with-config-file-scan-dir=/opt/bref/etc/php/conf.d:/var/task/php/conf.d \
140+
--enable-fpm \
141+
--disable-cgi \
142+
--enable-cli \
143+
--disable-phpdbg \
144+
--with-sodium \
145+
--with-readline \
146+
--with-openssl \
147+
--with-zlib \
148+
--with-curl \
149+
--enable-exif \
150+
--enable-ftp \
151+
--with-gettext \
152+
--enable-mbstring \
153+
--with-pdo-mysql=mysqlnd \
154+
--with-mysqli \
155+
--enable-pcntl \
156+
--with-zip \
157+
--enable-bcmath \
158+
--with-pdo-pgsql=shared \
159+
# Separate .so extension so that it is not loaded by default
160+
--enable-intl=shared \
161+
# Separate .so extension so that it is not loaded by default
162+
--enable-soap=shared \
163+
# Separate .so extension so that it is not loaded by default
164+
--with-xsl=${INSTALL_DIR} \
165+
--with-ffi \
166+
# necessary for `pecl` to work (to install PHP extensions)
167+
--with-pear \
168+
# extra compilation flags
169+
${PHP_COMPILATION_FLAGS}
170+
RUN make -j $(nproc)
171+
# Run `make install` and override PEAR's PHAR URL because pear.php.net is down
172+
RUN set -xe; \
173+
make install PEAR_INSTALLER_URL='https://github.com/pear/pearweb_phars/raw/master/install-pear-nozlib.phar'; \
174+
{ find ${INSTALL_DIR}/bin ${INSTALL_DIR}/sbin -type f -perm +0111 -exec strip --strip-all '{}' + || true; }; \
175+
make clean; \
176+
cp php.ini-production ${INSTALL_DIR}/etc/php/php.ini
177+
178+
179+
# Install extensions
180+
# We can install extensions manually or using `pecl`
181+
RUN pecl install APCu
182+
183+
184+
# ---------------------------------------------------------------
185+
# Now we copy everything we need for the layers into /bref-layer (which will be used for the real /opt later)
186+
RUN mkdir -p /bref-layer/bin \
187+
&& mkdir -p /bref-layer/lib \
188+
&& mkdir -p /bref-layer/bref/extensions \
189+
&& mkdir -p /bref-layer/bref/ssl
190+
191+
# Copy the PHP binary
192+
RUN cp ${INSTALL_DIR}/bin/php /bref-layer/bin/php && chmod +x /bref-layer/bin/php
193+
194+
# Copy the PHP-FPM binary
195+
RUN cp ${INSTALL_DIR}/sbin/php-fpm /bref-layer/bin/php-fpm
196+
197+
# Copy all the external PHP extensions
198+
RUN cp $(php -r 'echo ini_get("extension_dir");')/* /bref-layer/bref/extensions/
199+
200+
# Copy all the required system libraries from:
201+
# - /lib | /lib64 (system libraries installed with `dnf`)
202+
# - /opt/bin | /opt/lib | /opt/lib64 (libraries compiled from source)
203+
# into `/bref-layer` (the temp directory for the future Lambda layer)
204+
COPY --link utils/lib-copy /bref/lib-copy
205+
RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bin/php /bref-layer/lib
206+
RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bin/php-fpm /bref-layer/lib
207+
RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/apcu.so /bref-layer/lib
208+
RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/intl.so /bref-layer/lib
209+
RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/opcache.so /bref-layer/lib
210+
RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/pdo_mysql.so /bref-layer/lib
211+
RUN php /bref/lib-copy/copy-dependencies.php /bref-layer/bref/extensions/pdo_pgsql.so /bref-layer/lib
212+
213+
# Create a symbolic link to the OpenSSL certificates file for BC purposes
214+
RUN ln -s /etc/ssl/cert.pem /bref-layer/bref/ssl/cert.pem
215+
216+
# Run `strip` over all libraries and extensions to reduce their size
217+
RUN find /bref-layer/bref/extensions -type f -exec strip --strip-all {} +
218+
RUN find /bref-layer/lib -type f -exec strip --strip-all {} +
219+
220+
221+
# ----------------------------------------------------------------------------
222+
# Start from a clean image to copy only the files we need for the Lambda layer
223+
FROM public.ecr.aws/lambda/provided:al2023-${IMAGE_VERSION_SUFFIX} as function
224+
225+
# We selected the files in /bref-layer, now we copy them to /opt (the real directory for the Lambda layer)
226+
COPY --link --from=build-environment /bref-layer /opt
227+
228+
COPY --link src/php-85.ini /opt/bref/etc/php/conf.d/bref.ini
229+
COPY --link src/php-fpm.conf /opt/bref/etc/php-fpm.conf
230+
231+
COPY --link src/bootstrap.sh /opt/bootstrap
232+
# Copy files to /var/runtime to support deploying as a Docker image
233+
COPY --link src/bootstrap.sh /var/runtime/bootstrap
234+
RUN chmod +x /opt/bootstrap && chmod +x /var/runtime/bootstrap
235+
COPY --link src/bootstrap.php /opt/bref/bootstrap.php
236+
237+
238+
# ----------------------------------------------------------------------------
239+
# Build the dev image with xdebug
240+
FROM build-environment as build_dev
241+
242+
RUN mkdir -p /opt/bref/extensions
243+
244+
# Install xdebug
245+
# TODO xdebug is not available for PHP 8.5 yet
246+
#RUN pecl install xdebug-3.4.2
247+
#RUN cp $(php -r "echo ini_get('extension_dir');")/xdebug.so /opt/bref/extensions
248+
249+
250+
FROM function as dev
251+
252+
COPY --link --from=build_dev /opt /opt
253+
COPY --link src/dev-entrypoint.sh /bref-entrypoint.sh
254+
RUN chmod +x /bref-entrypoint.sh
255+
256+
# Install node to run the JS app below
257+
RUN dnf install -y nodejs
258+
259+
# Install the bref/local-api-gateway app in our container (avoids running 2 containers)
260+
COPY --link --from=bref/local-api-gateway /app /local-api-gateway
261+
EXPOSE 8000
262+
263+
# Add `php/conf.dev.d` to the path where PHP looks for configuration files
264+
ENV PHP_INI_SCAN_DIR="/opt/bref/etc/php/conf.d:/var/task/php/conf.d:/var/task/php/conf.dev.d"
265+
266+
# Add composer
267+
COPY --link --from=composer/composer:2-bin /composer /usr/bin/composer
268+
269+
# Originally the entrypoint is `/lambda-entrypoint.sh` and CMD contains the handler name
270+
# We override the entrypoint to run our own logic
271+
ENTRYPOINT [ "/bref-entrypoint.sh" ]

src/php-85.ini

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
; On the CLI we want errors to be sent to stdout -> those will end up in CloudWatch
2+
; In FPM workers we don't want that, but that is overridden by Bref when it starts PHP-FPM
3+
display_errors=1
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+
opcache.enable_cli=1
14+
15+
; Store the opcodes into a file cache (on top of storing in memory)
16+
; With FPM, this is only useful if FPM restarts or if the shared memory cache is full.
17+
; With the function runtime, this is useful when the function restarts the PHP
18+
; process on every invocation.
19+
; TODO store in a subdirectory (but the problem is that the subdirectory doesn't exist when PHP starts...)
20+
opcache.file_cache="/tmp"
21+
; Disable the memory cache since it's useless
22+
; In my tests it allows to gain 30% of response time in a classic API controller
23+
opcache.file_cache_only=1
24+
; Skip this check to save a bit
25+
opcache.validate_permission=0
26+
27+
; The code is readonly on lambdas so it never changes
28+
; This setting is now disabled: code could be written to /tmp which is read/write
29+
; (e.g. a compiled container) Such a performance optimization can be done by users.
30+
;opcache.validate_timestamps=0
31+
32+
; Set sane values, modern PHP applications have higher needs than opcache's defaults
33+
; See https://tideways.com/profiler/blog/fine-tune-your-opcache-configuration-to-avoid-caching-suprises
34+
opcache.memory_consumption=128
35+
opcache.max_accelerated_files=10000
36+
37+
; This directive determines which super global arrays are registered when PHP
38+
; starts up. G,P,C,E & S are abbreviations for the following respective super
39+
; globals: GET, POST, COOKIE, ENV and SERVER.
40+
; We explicitly populate all variables else ENV is not populated by default.
41+
; See https://github.com/brefphp/bref/pull/291
42+
variables_order="EGPCS"
43+
44+
; The lambda environment is not compatible with fastcgi_finish_request
45+
; See https://github.com/brefphp/bref/issues/214
46+
disable_functions=fastcgi_finish_request
47+
48+
; The total upload size limit is 6Mb, we override the defaults to match this limit
49+
; API Gateway has a 10Mb limit, but Lambda's is 6Mb
50+
post_max_size=6M
51+
upload_max_filesize=6M
52+
53+
extension_dir=/opt/bref/extensions

tests/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export CPU_PREFIX ?=
22

3-
test: test-82 test-83 test-84
3+
test: test-82 test-83 test-84 test-85
44

55
# This rule matches with a wildcard, for example `test-84`.
66
# The `$*` variable will contained the matched part, in this case `84`.

0 commit comments

Comments
 (0)