diff --git a/CHANGELOG.md b/CHANGELOG.md index afb1799a..781a425c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,15 @@ ### Minor changes +* **2026-10-05** + * The build now fails when an extension cannot be installed (failures were silently ignored) + * Fix rdkafka: installed from the stable package (6.0.5) instead of an alpha version, and now available on PHP 8.5 + * Fix Blackfire CLI missing since its versioning switched to calendar versions + * Fix swoole requiring mysqlnd + * Document the supported PHP and NodeJS versions + * Add the `decimal`, `gnupg`, `inotify`, `lz4`, `mcrypt`, `odbc`, `pdo_odbc` and `zstd` extensions on PHP 8.2+ + * Remove the unused `weakref` extension (PHP provides `WeakReference` natively since 7.4) + * **2025-11-26** * Support for PHP 8.5 diff --git a/Makefile b/Makefile index 2f605b69..fc6d742f 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ _test-prerequisites: blueprint test-hot: ## Test 7.4, 8.0 and 8.1 quickly docker buildx bake --load \ - --set "*.platform=$(uname -p)" \ + --set "*.platform=$$(docker version -f '{{.Server.Os}}/{{.Server.Arch}}')" \ php80-slim-cli php80-cli docker run --rm -it docker.io/thecodingmachine/php:8.0-v5-cli php -v test-legacy-quick: ## Test 7.4, 8.0 and 8.1 quickly @@ -56,21 +56,21 @@ test-node: ## Test node builds only _test-node: _test-prerequisites ## Test node for VERSION="" and VARIANT="" docker buildx bake --load \ - --set "*.platform=$(uname -p)" \ + --set "*.platform=$$(docker version -f '{{.Server.Os}}/{{.Server.Arch}}')" \ php$${VERSION//.}-$(VARIANT)-all PHP_VERSION="$(VERSION)" BRANCH=v5 VARIANT=$(VARIANT) NODE=$(NODE) ./tests-suite/bash_unit -f tap ./tests-suite/*.sh || (notify-send -u critical "Tests failed ($(VERSION)-$(VARIANT)-node$(NODE))" && exit 1) notify-send -u critical "Tests passed with success ($(VERSION)-$(VARIANT)-node$(NODE))" _test-version: _test-prerequisites ## Test php build for VERSION="" and VARIANT="" docker buildx bake --load \ - --set "*.platform=$(uname -p)" \ + --set "*.platform=$$(docker version -f '{{.Server.Os}}/{{.Server.Arch}}')" \ php$${VERSION//.}-$(VARIANT)-all PHP_VERSION="$(VERSION)" BRANCH=v5 VARIANT=$(VARIANT) ./tests-suite/bash_unit -f tap ./tests-suite/*.sh || (notify-send -u critical "Tests failed ($(VERSION)-$(VARIANT))" && exit 1) notify-send -u critical "Tests passed with success ($(VERSION)-$(VARIANT))" _test-version-quick: _test-prerequisites ## Test php build for VERSION="" and VARIANT="" (without node variants) docker buildx bake --load \ - --set "*.platform=$(uname -p)" \ + --set "*.platform=$$(docker version -f '{{.Server.Os}}/{{.Server.Arch}}')" \ php$${VERSION//.}-slim-$(VARIANT) php$${VERSION//.}-$(VARIANT) PHP_VERSION="$(VERSION)" BRANCH=v5 VARIANT=$(VARIANT) ./tests-suite/bash_unit -f tap ./tests-suite/*.sh || (notify-send -u critical "Tests failed ($(VERSION)-$(VARIANT))" && exit 1) notify-send -u critical "Tests passed with success ($(VERSION)-$(VARIANT)) - without node-*" diff --git a/README.md b/README.md index 8d44e0c0..8858a43a 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,30 @@ Also, we automatically rebuild X.Y images every week, but only the latest X.Y.Z [Major].[minor] images are automatically updated when a new patch version of PHP is released, so the PHP 8.4 image will always contain the most up-to-date version of the PHP 8.4.x branch. +## Supported versions + +We only maintain the PHP and NodeJS versions that are still supported by their respective communities +(see [PHP supported versions](https://www.php.net/supported-versions.php) and [NodeJS releases](https://nodejs.org/en/about/previous-releases)). +Bugs are fixed on maintained versions only. + +| PHP version | Status | +|-------------|-----------------------------------------------| +| 8.5 | Maintained (until 2029-12-31) | +| 8.4 | Maintained (until 2028-12-31) | +| 8.3 | Maintained (until 2027-12-31) | +| 8.2 | Maintained (until 2026-12-31) | +| 8.1 | **Not maintained** (end of life: 2025-12-31) | +| 8.0 | **Not maintained** (end of life: 2023-11-26) | +| 7.4 | **Not maintained** (end of life: 2022-11-28) | + +| NodeJS version | Status | +|----------------|-----------------------------------------------| +| 24 | Maintained (until 2028-04-30) | +| 22 | Maintained (until 2027-04-30) | +| 20 | **Not maintained** (end of life: 2026-04-30) | + +Images of non-maintained versions are still available but no longer receive fixes: use them at your own risk and plan your upgrade. + ## Usage These images are based on the [official PHP image](https://hub.docker.com/_/php/). @@ -159,13 +183,14 @@ Below is a list of extensions available in this image: **Enabled by default (in addition to extensions enabled in Slim image):** `apcu`, `hash`, `iconv`, `igbinary`, `mysqli`, `mysqlnd`, `redis`, `soap`, `xsl`, `zlib` and all enabled in slim. -**Available (can be enabled using environment variables):** `amqp` `ast` `bcmath` `blackfire` `bz2` `dba` `ds` `enchant` `exif` `excimer` `ffi` `mailparse` `msgpack` `gd` `gettext` `gmp` `grpc` `igbinary` `imagick` `imap` `intl` `ldap` `memcached` `mongodb` `pcov` `pdo_dblib` `pdo_pgsql` `pdo_sqlite` `pgsql` `pspell` `shmop` `snmp` `sockets` `sqlite3` `swoole` `tidy` `uploadprogress` `uuid` `xdebug` `xmlrpc` `xsl` `yaml` +**Available (can be enabled using environment variables):** `amqp` `ast` `bcmath` `blackfire` `bz2` `dba` `decimal` `ds` `enchant` `exif` `excimer` `ffi` `mailparse` `msgpack` `gd` `gettext` `gmp` `gnupg` `grpc` `igbinary` `imagick` `imap` `inotify` `intl` `ldap` `lz4` `mcrypt` `memcached` `mongodb` `odbc` `pcov` `pdo_dblib` `pdo_odbc` `pdo_pgsql` `pdo_sqlite` `pgsql` `pspell` `rdkafka` `shmop` `snmp` `sockets` `sqlite3` `swoole` `tidy` `uploadprogress` `uuid` `xdebug` `xmlrpc` `xsl` `yaml` `zstd` This list can be outdated, you can verify by executing : `docker run --rm -it thecodingmachine/php:8.4-v5-cli php -m` **Note**: - *ev* is not available in PHP 8.1+ +- *mcrypt* is deprecated and its usage is discouraged: it is provided for legacy applications only ### Enabling/disabling extensions in the fat image @@ -363,9 +388,9 @@ The *fat* images come with a Node variant. You can use Node : 20 22 24. If you n If you use the *slim* images, you can install a NodeJS version with a simple ARG during the build: ```Dockerfile -ARG NODE_VERSION=18 +ARG NODE_VERSION=24 FROM thecodingmachine/php:8.4-v5-slim-apache -# The build will automatically trigger the download of Node 18 +# The build will automatically trigger the download of Node 24 # (thanks to a ONBUILD hook in the slim image) ``` diff --git a/extensions/8.2/decimal b/extensions/8.2/decimal new file mode 120000 index 00000000..cbe7097d --- /dev/null +++ b/extensions/8.2/decimal @@ -0,0 +1 @@ +../core/decimal \ No newline at end of file diff --git a/extensions/8.2/gnupg b/extensions/8.2/gnupg new file mode 120000 index 00000000..002cc7b2 --- /dev/null +++ b/extensions/8.2/gnupg @@ -0,0 +1 @@ +../core/gnupg \ No newline at end of file diff --git a/extensions/8.2/inotify b/extensions/8.2/inotify new file mode 120000 index 00000000..d1a857c1 --- /dev/null +++ b/extensions/8.2/inotify @@ -0,0 +1 @@ +../core/inotify \ No newline at end of file diff --git a/extensions/8.2/lz4 b/extensions/8.2/lz4 new file mode 120000 index 00000000..5922a3b4 --- /dev/null +++ b/extensions/8.2/lz4 @@ -0,0 +1 @@ +../core/lz4 \ No newline at end of file diff --git a/extensions/8.2/mcrypt b/extensions/8.2/mcrypt new file mode 120000 index 00000000..f548d014 --- /dev/null +++ b/extensions/8.2/mcrypt @@ -0,0 +1 @@ +../core/mcrypt \ No newline at end of file diff --git a/extensions/8.2/odbc b/extensions/8.2/odbc new file mode 120000 index 00000000..32fcd6ce --- /dev/null +++ b/extensions/8.2/odbc @@ -0,0 +1 @@ +../core/odbc \ No newline at end of file diff --git a/extensions/8.2/pdo_odbc b/extensions/8.2/pdo_odbc new file mode 120000 index 00000000..32fcd6ce --- /dev/null +++ b/extensions/8.2/pdo_odbc @@ -0,0 +1 @@ +../core/odbc \ No newline at end of file diff --git a/extensions/8.2/zstd b/extensions/8.2/zstd new file mode 120000 index 00000000..b65d02b6 --- /dev/null +++ b/extensions/8.2/zstd @@ -0,0 +1 @@ +../core/zstd \ No newline at end of file diff --git a/extensions/8.3/decimal b/extensions/8.3/decimal new file mode 120000 index 00000000..cbe7097d --- /dev/null +++ b/extensions/8.3/decimal @@ -0,0 +1 @@ +../core/decimal \ No newline at end of file diff --git a/extensions/8.3/gnupg b/extensions/8.3/gnupg new file mode 120000 index 00000000..002cc7b2 --- /dev/null +++ b/extensions/8.3/gnupg @@ -0,0 +1 @@ +../core/gnupg \ No newline at end of file diff --git a/extensions/8.3/inotify b/extensions/8.3/inotify new file mode 120000 index 00000000..d1a857c1 --- /dev/null +++ b/extensions/8.3/inotify @@ -0,0 +1 @@ +../core/inotify \ No newline at end of file diff --git a/extensions/8.3/lz4 b/extensions/8.3/lz4 new file mode 120000 index 00000000..5922a3b4 --- /dev/null +++ b/extensions/8.3/lz4 @@ -0,0 +1 @@ +../core/lz4 \ No newline at end of file diff --git a/extensions/8.3/mcrypt b/extensions/8.3/mcrypt new file mode 120000 index 00000000..f548d014 --- /dev/null +++ b/extensions/8.3/mcrypt @@ -0,0 +1 @@ +../core/mcrypt \ No newline at end of file diff --git a/extensions/8.3/odbc b/extensions/8.3/odbc new file mode 120000 index 00000000..32fcd6ce --- /dev/null +++ b/extensions/8.3/odbc @@ -0,0 +1 @@ +../core/odbc \ No newline at end of file diff --git a/extensions/8.3/pdo_odbc b/extensions/8.3/pdo_odbc new file mode 120000 index 00000000..32fcd6ce --- /dev/null +++ b/extensions/8.3/pdo_odbc @@ -0,0 +1 @@ +../core/odbc \ No newline at end of file diff --git a/extensions/8.3/zstd b/extensions/8.3/zstd new file mode 120000 index 00000000..b65d02b6 --- /dev/null +++ b/extensions/8.3/zstd @@ -0,0 +1 @@ +../core/zstd \ No newline at end of file diff --git a/extensions/8.4/decimal b/extensions/8.4/decimal new file mode 120000 index 00000000..cbe7097d --- /dev/null +++ b/extensions/8.4/decimal @@ -0,0 +1 @@ +../core/decimal \ No newline at end of file diff --git a/extensions/8.4/gnupg b/extensions/8.4/gnupg new file mode 120000 index 00000000..002cc7b2 --- /dev/null +++ b/extensions/8.4/gnupg @@ -0,0 +1 @@ +../core/gnupg \ No newline at end of file diff --git a/extensions/8.4/inotify b/extensions/8.4/inotify new file mode 120000 index 00000000..d1a857c1 --- /dev/null +++ b/extensions/8.4/inotify @@ -0,0 +1 @@ +../core/inotify \ No newline at end of file diff --git a/extensions/8.4/lz4 b/extensions/8.4/lz4 new file mode 120000 index 00000000..5922a3b4 --- /dev/null +++ b/extensions/8.4/lz4 @@ -0,0 +1 @@ +../core/lz4 \ No newline at end of file diff --git a/extensions/8.4/mcrypt b/extensions/8.4/mcrypt new file mode 120000 index 00000000..f548d014 --- /dev/null +++ b/extensions/8.4/mcrypt @@ -0,0 +1 @@ +../core/mcrypt \ No newline at end of file diff --git a/extensions/8.4/odbc b/extensions/8.4/odbc new file mode 120000 index 00000000..32fcd6ce --- /dev/null +++ b/extensions/8.4/odbc @@ -0,0 +1 @@ +../core/odbc \ No newline at end of file diff --git a/extensions/8.4/pdo_odbc b/extensions/8.4/pdo_odbc new file mode 120000 index 00000000..32fcd6ce --- /dev/null +++ b/extensions/8.4/pdo_odbc @@ -0,0 +1 @@ +../core/odbc \ No newline at end of file diff --git a/extensions/8.4/zstd b/extensions/8.4/zstd new file mode 120000 index 00000000..b65d02b6 --- /dev/null +++ b/extensions/8.4/zstd @@ -0,0 +1 @@ +../core/zstd \ No newline at end of file diff --git a/extensions/8.5/decimal b/extensions/8.5/decimal new file mode 120000 index 00000000..cbe7097d --- /dev/null +++ b/extensions/8.5/decimal @@ -0,0 +1 @@ +../core/decimal \ No newline at end of file diff --git a/extensions/8.5/gnupg b/extensions/8.5/gnupg new file mode 120000 index 00000000..002cc7b2 --- /dev/null +++ b/extensions/8.5/gnupg @@ -0,0 +1 @@ +../core/gnupg \ No newline at end of file diff --git a/extensions/8.5/inotify b/extensions/8.5/inotify new file mode 120000 index 00000000..d1a857c1 --- /dev/null +++ b/extensions/8.5/inotify @@ -0,0 +1 @@ +../core/inotify \ No newline at end of file diff --git a/extensions/8.5/lz4 b/extensions/8.5/lz4 new file mode 120000 index 00000000..5922a3b4 --- /dev/null +++ b/extensions/8.5/lz4 @@ -0,0 +1 @@ +../core/lz4 \ No newline at end of file diff --git a/extensions/8.5/mcrypt b/extensions/8.5/mcrypt new file mode 120000 index 00000000..f548d014 --- /dev/null +++ b/extensions/8.5/mcrypt @@ -0,0 +1 @@ +../core/mcrypt \ No newline at end of file diff --git a/extensions/8.5/odbc b/extensions/8.5/odbc new file mode 120000 index 00000000..32fcd6ce --- /dev/null +++ b/extensions/8.5/odbc @@ -0,0 +1 @@ +../core/odbc \ No newline at end of file diff --git a/extensions/8.5/pdo_odbc b/extensions/8.5/pdo_odbc new file mode 120000 index 00000000..32fcd6ce --- /dev/null +++ b/extensions/8.5/pdo_odbc @@ -0,0 +1 @@ +../core/odbc \ No newline at end of file diff --git a/extensions/8.5/zstd b/extensions/8.5/zstd new file mode 120000 index 00000000..b65d02b6 --- /dev/null +++ b/extensions/8.5/zstd @@ -0,0 +1 @@ +../core/zstd \ No newline at end of file diff --git a/extensions/core/blackfire/install.sh b/extensions/core/blackfire/install.sh index f62bca7f..344e535d 100755 --- a/extensions/core/blackfire/install.sh +++ b/extensions/core/blackfire/install.sh @@ -31,7 +31,7 @@ elif [[ "${BLACKFIRE_VERSION}" == "2" ]]; then echo "Installing Blackfire version 2..." mkdir -p /tmp/blackfire curl -A "Docker" -L https://blackfire.io/api/v1/releases/cli/linux/${TARGETARCH} | tar zxp -C /tmp/blackfire - if ! /tmp/blackfire/blackfire self:version --no-ansi | grep -qE "version 2\.[0-9]+\.[0-9]+"; then + if ! /tmp/blackfire/blackfire self:version --no-ansi | grep -qE "version (2|20[0-9]{2})\.[0-9]+\.[0-9]+"; then echo "Blackfire installed is not version 2 : $(/tmp/blackfire/blackfire self:version --no-ansi)" exit 1 fi diff --git a/extensions/core/decimal/install.sh b/extensions/core/decimal/install.sh new file mode 100755 index 00000000..52641560 --- /dev/null +++ b/extensions/core/decimal/install.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -e +export EXTENSION=decimal + +../docker-install.sh diff --git a/extensions/core/docker-install.sh b/extensions/core/docker-install.sh index fa49822e..c407fceb 100755 --- a/extensions/core/docker-install.sh +++ b/extensions/core/docker-install.sh @@ -11,16 +11,20 @@ if [ -n "$CONFIGURE_OPTIONS" ]; then fi if [ -n "$EXTENSION" ]; then - set +e - PACKAGE_NAME=${PACKAGE_NAME:-$EXTENSION} - if apt-cache search --names-only "php${PHP_VERSION}-$PACKAGE_NAME" | grep "php${PHP_VERSION}-$PACKAGE_NAME"; then - set -e - apt install -y --no-install-recommends php${PHP_VERSION}-$PACKAGE_NAME + if [ -f "/etc/php/${PHP_VERSION}/mods-available/${EXTENSION}.ini" ]; then + # Some extensions are bundled in php-common on recent versions (e.g. ffi and gettext on PHP 8.5): nothing to install. + echo "Extension ${EXTENSION} is already provided, skipping package installation" else - set -e - apt install -y --no-install-recommends php-$PACKAGE_NAME + set +e + PACKAGE_NAME=${PACKAGE_NAME:-$EXTENSION} + if apt-cache search --names-only "php${PHP_VERSION}-$PACKAGE_NAME" | grep "php${PHP_VERSION}-$PACKAGE_NAME"; then + set -e + apt install -y --no-install-recommends php${PHP_VERSION}-$PACKAGE_NAME + else + set -e + apt install -y --no-install-recommends php-$PACKAGE_NAME + fi fi - fi if [ -n "$PECL_EXTENSION" ]; then diff --git a/extensions/core/ffi/install.sh b/extensions/core/ffi/install.sh index 6ee7e0ba..c2d743d2 100755 --- a/extensions/core/ffi/install.sh +++ b/extensions/core/ffi/install.sh @@ -2,5 +2,7 @@ set -e export EXTENSION=ffi +# php -m displays "FFI" (uppercase) +export PHP_EXT_PHP_NAME=FFI ../docker-install.sh diff --git a/extensions/core/inotify/install.sh b/extensions/core/inotify/install.sh new file mode 100755 index 00000000..862676d7 --- /dev/null +++ b/extensions/core/inotify/install.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -e +export EXTENSION=inotify + +../docker-install.sh diff --git a/extensions/core/install_all.sh b/extensions/core/install_all.sh index 73781592..19cfa543 100755 --- a/extensions/core/install_all.sh +++ b/extensions/core/install_all.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash set -e +set -o pipefail set +x # Let's disable autoclean of package list after apt install @@ -10,18 +11,29 @@ apt update mkdir -p /var/log/ext-php/ +FAILED_EXTENSIONS=() + for ext in */; do \ cd $ext ext_no_slash=${ext%/} echo "***************** Installing $ext_no_slash ******************" LOG="/var/log/ext-php/install-${ext_no_slash}" start=$(date +%s) - ./install.sh 2>&1 | tee -a "${LOG}.log" + if ! ./install.sh 2>&1 | tee -a "${LOG}.log"; then + FAILED_EXTENSIONS+=("${ext_no_slash}") + # Disable the failed extension so that it does not break the checks of the next ones + phpdismod -v "${PHP_VERSION}" "${ext_no_slash}" || true + fi end=$(date +%s) echo "$(($end-$start)) seconds to execute ${ext_no_slash}" > "${LOG}.time" cd .. done +if [ ${#FAILED_EXTENSIONS[@]} -ne 0 ]; then + echo "***************** Failed extensions: ${FAILED_EXTENSIONS[*]} ******************" + exit 1 +fi + # Let's enable autoclean again mv /tmp/docker-clean /etc/apt/apt.conf.d/docker-clean diff --git a/extensions/core/lz4/install.sh b/extensions/core/lz4/install.sh new file mode 100755 index 00000000..1ac4d0dd --- /dev/null +++ b/extensions/core/lz4/install.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -e +export EXTENSION=lz4 + +../docker-install.sh diff --git a/extensions/core/odbc/install.sh b/extensions/core/odbc/install.sh new file mode 100755 index 00000000..02ee8c87 --- /dev/null +++ b/extensions/core/odbc/install.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e +# Installs both odbc and pdo_odbc +export EXTENSION=odbc + +../docker-install.sh diff --git a/extensions/core/rdkafka/install.sh b/extensions/core/rdkafka/install.sh index 4a26d0c6..c0dfcb03 100755 --- a/extensions/core/rdkafka/install.sh +++ b/extensions/core/rdkafka/install.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash set -e -export DEV_DEPENDENCIES="librdkafka-dev" -export DEPENDENCIES="librdkafka1" -PECL_EXTENSION=rdkafka ../docker-install.sh +export EXTENSION=rdkafka + +../docker-install.sh diff --git a/extensions/core/swoole/install.sh b/extensions/core/swoole/install.sh index d47cad22..e26b37d6 100755 --- a/extensions/core/swoole/install.sh +++ b/extensions/core/swoole/install.sh @@ -4,4 +4,7 @@ set -e export EXTENSION=swoole +# swoole requires mysqlnd to be loaded (installed by pdo_mysql) +phpenmod -v $PHP_VERSION mysqlnd ../docker-install.sh +phpdismod -v $PHP_VERSION mysqlnd diff --git a/extensions/core/weakref/install.sh b/extensions/core/weakref/install.sh deleted file mode 100755 index 40645dc1..00000000 --- a/extensions/core/weakref/install.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -set -e -export PECL_EXTENSION=weakref-beta -export PHP_EXT_NAME=weakref # name of the extension (to put in PHP_EXTENSIONS variable) -export PHP_EXT_PHP_NAME=Weakref # name of the extension (as displayed in the output of "php -m") - -../docker-install.sh diff --git a/extensions/core/zstd/install.sh b/extensions/core/zstd/install.sh new file mode 100755 index 00000000..3be6eec2 --- /dev/null +++ b/extensions/core/zstd/install.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -e +export EXTENSION=zstd + +../docker-install.sh diff --git a/tests-suite/config b/tests-suite/config index e9b34260..f1895fd4 100755 --- a/tests-suite/config +++ b/tests-suite/config @@ -1,5 +1,5 @@ #!/usr/bin/env bash -export PLATFORM="${PLATFORM:-$(uname -p)}" +export PLATFORM="${PLATFORM:-$(docker version -f '{{.Server.Os}}/{{.Server.Arch}}')}" export BUILDTOOL="build --platform=${PLATFORM}" export RUN_OPTIONS="--platform=${PLATFORM}" export PHP_VERSION=${PHP_VERSION:-8.4} diff --git a/tests-suite/php-extensions.sh b/tests-suite/php-extensions.sh index 9920da7d..c52d88c9 100755 --- a/tests-suite/php-extensions.sh +++ b/tests-suite/php-extensions.sh @@ -31,20 +31,39 @@ test_presenceOfFFIOnFat() { RESULT=$(docker run ${RUN_OPTIONS} -e "PHP_EXTENSIONS=ffi" --rm "${REPO}:${TAG_PREFIX}${PHP_VERSION}-${BRANCH}-${BRANCH_VARIANT}${ARCH_SUFFIX}" php -m | tail -n +1 | grep --color=never FFI) assert_equals "FFI" "${RESULT}" "Missing php-FFI" } +################################################################# +## Let's check that extensions added in PHP 8.2+ images +## are enabled explicitly with fat +################################################################# +test_presenceOfPhp82ExtensionsOnFat() { + # Only available on PHP 8.2+ + if [[ "$(printf '%s\n' "$PHP_VERSION" "8.2" | sort -V | head -n 1)" != "8.2" ]]; then return 0; fi + # Extension name in PHP_EXTENSIONS => name displayed by "php -m" + declare -A EXTENSIONS=([gnupg]=gnupg [mcrypt]=mcrypt [odbc]=odbc [pdo_odbc]=PDO_ODBC [zstd]=zstd [lz4]=lz4 [decimal]=decimal [inotify]=inotify) + MODULES=$(docker run ${RUN_OPTIONS} -e "PHP_EXTENSIONS=${!EXTENSIONS[*]}" --rm "${REPO}:${TAG_PREFIX}${PHP_VERSION}-${BRANCH}-${BRANCH_VARIANT}${ARCH_SUFFIX}" php -m | tail -n +1) + for EXTENSION in "${!EXTENSIONS[@]}"; do + RESULT=$(echo "${MODULES}" | grep --color=never -x "${EXTENSIONS[$EXTENSION]}") + assert_equals "${EXTENSIONS[$EXTENSION]}" "${RESULT}" "Missing php-${EXTENSION}" + done +} ############################################################ ## Let's check that the extensions are enabled when composer is run ############################################################ test_enableGdWithComposer() { - docker $BUILDTOOL -t test/composer_with_gd \ + docker $BUILDTOOL -t "${COMPOSER_GD_NAME}" \ --build-arg PHP_VERSION="${PHP_VERSION}" --build-arg BRANCH="$BRANCH" \ --build-arg BRANCH_VARIANT="$BRANCH_VARIANT" --build-arg REPO="$REPO" --build-arg TAG_PREFIX="$TAG_PREFIX" --build-arg ARCH_SUFFIX="$ARCH_SUFFIX" \ "${SCRIPT_DIR}/assets/composer" > /dev/null 2>&1 assert_equals "0" "$?" "Docker build failed" # This should run ok (the sudo disables environment variables but call to composer proxy does not trigger PHP ini file regeneration) - docker run ${RUN_OPTIONS} --rm test/composer_with_gd sudo composer update > /dev/null 2>&1 + docker run ${RUN_OPTIONS} --rm "${COMPOSER_GD_NAME}" sudo composer update > /dev/null 2>&1 assert_equals "0" "$?" "Docker run failed" } +setup_suite() { + export COMPOSER_GD_NAME="test/composer_with_gd_$(unused_port)" +} + teardown_suite() { - docker rmi test/composer_with_gd > /dev/null 2>&1 + docker rmi "${COMPOSER_GD_NAME}" > /dev/null 2>&1 } diff --git a/tests-suite/variant-fpm.sh b/tests-suite/variant-fpm.sh index a341d036..6fc5e119 100755 --- a/tests-suite/variant-fpm.sh +++ b/tests-suite/variant-fpm.sh @@ -9,16 +9,20 @@ fi; ## Test if environment starts without errors ############################################################ test_start() { - docker run --name test-fpm1 ${RUN_OPTIONS} --rm -e MYVAR=foo -e PHP_INI_MEMORY_LIMIT=2G -p "9001:9000" -d -v "${SCRIPT_DIR}/assets/":/var/www/html \ + docker run --name "${FPM_CONTAINER_NAME}" ${RUN_OPTIONS} --rm -e MYVAR=foo -e PHP_INI_MEMORY_LIMIT=2G -p "$(unused_port):9000" -d -v "${SCRIPT_DIR}/assets/":/var/www/html \ "${REPO}:${TAG_PREFIX}${PHP_VERSION}-${BRANCH}-slim-${BRANCH_VARIANT}${ARCH_SUFFIX}" > /dev/null assert_equals "0" "$?" "Docker run failed" # Let's wait for FPM to start sleep 3 # If the container is still up, it will not fail when stopping. - docker stop test-fpm1 > /dev/null 2>&1 + docker stop "${FPM_CONTAINER_NAME}" > /dev/null 2>&1 assert_equals "0" "$?" "Docker stop failed" } +setup_suite() { + export FPM_CONTAINER_NAME="test-fpm-$(unused_port)" +} + teardown_suite() { - docker stop test-fpm1 > /dev/null 2>&1 + docker stop "${FPM_CONTAINER_NAME}" > /dev/null 2>&1 } diff --git a/utils/README.blueprint.md b/utils/README.blueprint.md index 6157630b..ce4b92b7 100644 --- a/utils/README.blueprint.md +++ b/utils/README.blueprint.md @@ -40,6 +40,30 @@ Also, we automatically rebuild X.Y images every week, but only the latest X.Y.Z [Major].[minor] images are automatically updated when a new patch version of PHP is released, so the PHP {{ $image.php_version }} image will always contain the most up-to-date version of the PHP {{ $image.php_version }}.x branch. +## Supported versions + +We only maintain the PHP and NodeJS versions that are still supported by their respective communities +(see [PHP supported versions](https://www.php.net/supported-versions.php) and [NodeJS releases](https://nodejs.org/en/about/previous-releases)). +Bugs are fixed on maintained versions only. + +| PHP version | Status | +|-------------|-----------------------------------------------| +| 8.5 | Maintained (until 2029-12-31) | +| 8.4 | Maintained (until 2028-12-31) | +| 8.3 | Maintained (until 2027-12-31) | +| 8.2 | Maintained (until 2026-12-31) | +| 8.1 | **Not maintained** (end of life: 2025-12-31) | +| 8.0 | **Not maintained** (end of life: 2023-11-26) | +| 7.4 | **Not maintained** (end of life: 2022-11-28) | + +| NodeJS version | Status | +|----------------|-----------------------------------------------| +| 24 | Maintained (until 2028-04-30) | +| 22 | Maintained (until 2027-04-30) | +| 20 | **Not maintained** (end of life: 2026-04-30) | + +Images of non-maintained versions are still available but no longer receive fixes: use them at your own risk and plan your upgrade. + ## Usage These images are based on the [official PHP image](https://hub.docker.com/_/php/). @@ -92,13 +116,14 @@ Below is a list of extensions available in this image: **Enabled by default (in addition to extensions enabled in Slim image):** `apcu`, `hash`, `iconv`, `igbinary`, `mysqli`, `mysqlnd`, `redis`, `soap`, `xsl`, `zlib` and all enabled in slim. -**Available (can be enabled using environment variables):** `amqp` `ast` `bcmath` `blackfire` `bz2` `dba` `ds` `enchant` `exif` `excimer` `ffi` `mailparse` `msgpack` `gd` `gettext` `gmp` `grpc` `igbinary` `imagick` `imap` `intl` `ldap` `memcached` `mongodb` `pcov` `pdo_dblib` `pdo_pgsql` `pdo_sqlite` `pgsql` `pspell` `shmop` `snmp` `sockets` `sqlite3` `swoole` `tidy` `uploadprogress` `uuid` `xdebug` `xmlrpc` `xsl` `yaml` +**Available (can be enabled using environment variables):** `amqp` `ast` `bcmath` `blackfire` `bz2` `dba` `decimal` `ds` `enchant` `exif` `excimer` `ffi` `mailparse` `msgpack` `gd` `gettext` `gmp` `gnupg` `grpc` `igbinary` `imagick` `imap` `inotify` `intl` `ldap` `lz4` `mcrypt` `memcached` `mongodb` `odbc` `pcov` `pdo_dblib` `pdo_odbc` `pdo_pgsql` `pdo_sqlite` `pgsql` `pspell` `rdkafka` `shmop` `snmp` `sockets` `sqlite3` `swoole` `tidy` `uploadprogress` `uuid` `xdebug` `xmlrpc` `xsl` `yaml` `zstd` This list can be outdated, you can verify by executing : `docker run --rm -it thecodingmachine/php:{{ $image.php_version }}-v5-cli php -m` **Note**: - *ev* is not available in PHP 8.1+ +- *mcrypt* is deprecated and its usage is discouraged: it is provided for legacy applications only ### Enabling/disabling extensions in the fat image @@ -296,9 +321,9 @@ The *fat* images come with a Node variant. You can use Node :{{range $nodeV := $ If you use the *slim* images, you can install a NodeJS version with a simple ARG during the build: ```Dockerfile -ARG NODE_VERSION=18 +ARG NODE_VERSION=24 FROM thecodingmachine/php:{{ $image.php_version }}-v5-slim-apache -# The build will automatically trigger the download of Node 18 +# The build will automatically trigger the download of Node 24 # (thanks to a ONBUILD hook in the slim image) ``` diff --git a/utils/setup_extensions.php b/utils/setup_extensions.php index 68a0e80e..dc3ebddf 100755 --- a/utils/setup_extensions.php +++ b/utils/setup_extensions.php @@ -55,8 +55,8 @@ } } -// mysqlnd is a dependency required for mysqli or pdo_mysql -if (enableExtension('mysqli') || enableExtension('pdo_mysql')) { +// mysqlnd is a dependency required for mysqli, pdo_mysql or swoole +if (enableExtension('mysqli') || enableExtension('pdo_mysql') || enableExtension('swoole')) { $toEnable['mysqlnd'] = 'mysqlnd'; unset($toDisable['mysqlnd']); }