### Added
- Add PHPFPM_POOL__INCLUDES to add external include configuration
- Add ..._LISTEN_TYPE=both support spawning shadow pools with -tcp suffix
### Changed
- Migrate to write_file for remaining tee commands
## 8.0.6 2026-05-10
### Changed
- Add --remove destination to limit downstream image configurations destroying source of truth
## 8.0.5 2026-04-22
### Changed
- Fix abliity to use downstream images with 8.0.4
## 8.0.4 2026-04-22
### Changed
- Fix sisues with Zabbix monitoring (ping/php-fpm_status) URLs
- Rework Opcache Monitoring scripts to be dynamically created in /usr/share/zabbix/php-opcache instead of zabbix permission locked config folder
## 8.0.3 2026-04-20
### Changed
- Tag to support changes in nfrastack/containre-nginx:8.0.7
## 8.0.2 2026-03-26
### Added
- Support BUILD_ENV
### Changed
- Rewrite php-ext operations
- Repair monitoring configuration routines
- Support upstream base image features better
## 8.0.1 2026-02-24
### Changed
- Upstream and index placeholder repairs
## 8.0.0 2026-02-23
### Added
- Supporting PHP 8.5 and Alpine 3.23
- Multiple Pool Support
- Many differnet customization options
- Dynamic configuration of PHP location block
- Uses nfrastack/container-nginx:8.x.x as base image
## 7.7.20 2025-08-16
### Changed
- Change php8.1-alpine to use alpine 3.18 base with prebuilt images
## 7.7.19 2025-04-27
### Added
- Pin to tiredofit/nginx:6.5.18
## 7.7.18 2025-04-25
### Added
- Pin to tiredofit/nginx:6.5.17
## 7.7.17 2024-12-19
### Reverted
- Remove php84-spell component to support building under Alpine
## 7.7.16 2024-12-12
### Added
- Pin to tiredofit/nginx:6.5.10
## 7.7.15 2024-12-09
### Added
- Alpine pin to tiredofit/nginx:6.5.8
## 7.7.14 2024-12-07
### Added
- Add PHP 8.4 Support
### Changed
- Switch PHP 8.3 and PHP 8.2 to use Alpine 3.21 as base
## 7.7.13 2024-10-22
### Added
- Pin to tiredofit/nginx:6.5.4
## 7.7.12 2024-10-04
### Added
- Pin to tiredofit/alpine:6.5.3
## 7.7.11 2024-09-26
### Changed
- Cleanup php-ext script
- Pin to tiredofit/nginx:6.5.2
## 7.7.10 2024-09-25
### Added
- Add php-ext disable reset statement to refresh environments
## 7.7.9 2024-09-25
### Changed
- Remove stray cat command in Dockerfile
## 7.7.8 2024-05-01
### Changed
- Change sury.org GPG key for Debian installations
## 7.7.7 2024-04-16
### Added
- Add php83 extensions: ds,event,grpc,imagick,opentelemetry,pcov,rdkafka,smblient,ssh2
- Add php82 extensions: decimal,ds,event,grpc,mailparse,mcrypt,opentelemetry,pcov,rdkafka,smbclient,ssh2,timezonedb,vips,xlswriter
- Add php81 extensions: decimal,ds,luasandbox,mcrypt,opentelemetry,pcov,smbclient
## 7.7.6 2024-02-16
### Changed
- Remove Suhosin from hp5.6 variant
## 7.7.5 2024-01-26
### Reverted
- Remove lz4 extension from Debian variant
## 7.7.4 2023-12-08
### Changed
- Add alpine:3.19
## 7.7.3 2023-12-05
### Changed
- Change build for Alpine PHP 8.3 to not include 4 PECL extensions
## 7.7.2 2023-11-28
### Reverted
- Drop php-lua extension
## 7.7.1 2023-11-28
### Changed
- Remove `BOTH` Option for PHP_FPM_LISTEN_TYPE
## 7.7.0 2023-11-25
### Added
- Allow listening on Unix Socket or TCP Socket (default Unix Socket)
- Add host/ip restrictions for TCP listening
- Add PHP_FPM_USER and PHP_FPM_GROUP variables to create isolation from upstream image (default NGINX_ or UNIT_ USER|GROUP)
## 7.6.16 2023-11-22
### Added
- Introduce PHP 8.3 support
## 7.6.15 2023-09-13
### Changed
- Fix PHP_TIMEOUT not affecting php-cli operations causing unnecessary Signal 15s in some cases
## 7.6.14 2023-09-05
### Changed
- Fixed not working LLNG handler authentification
- Fixed creating a default index page
## 7.6.13 2023-07-28
### Reverted
- Remove php-decimal extension from Debian variant
## 7.6.12 2023-07-28
### Added
- Add support for Debian Bookworm
### Changed
- Cleanup some PHP directories that shouldn't exist on Debian variants
## 7.6.11 2023-07-25
### Changed
- Change environment variable case
## 7.6.10 2023-07-06
### Added
- Source defaults from upstream nginx container to avoid having to use NGINX_ENABLE_APPLICATION_CONFIGURATION=TRUE variable
## 7.6.9 2023-06-21
### Changed
- Fix case introduced with 7.6.8 where authentication takes over default settings
## 7.6.8 2023-06-20
### Changed
- Restructure authentication routines when no NGINX_SITE_ENABLED being used to properly allow NGINX_AUTHENTICATION_TYPE=LLNG to be used.
## 7.6.6 2023-06-19
### Changed
- Stop building gnupg extension for
### Changed
- Drop requirement of gnu-libiconv for < PHP 8.0 on alpine
## 7.6.4 2023-05-12
### Reverted
- Remove php82-pecl-phalcon for Alpine 3.18
## 7.6.3 2023-05-12
### Changed
- Strip pecl packages that no longer exist in Arch 3.18 repository for PHP 8.2
## 7.6.2 2023-05-10
### Changed
- Change PHP 8.2 to build with Alpine 3.18 Base
- Change PHP 8.1 to build with Alpine 3.18 Base
- Drop PHP 3.17 base variant
## 7.6.1 2023-04-04
### Reverted
- Remove spx extension from PHP 8.2 alpine
## 7.6.0 2023-03-24
### Added
- Added dozens of extra modules for Alpine PHP 8.0, 8.1, 8.2 variants
## 7.5.6 2023-03-23
### Changed
- Load MSGPACK when loading Redis module
## 7.5.5 2023-03-23
### Added
- Add more OPCache options and fix broken options
## 7.5.4 2023-03-23
### Added
- Add testing repository for PHP 8.2-alpine
## 7.5.3 2023-03-23
### Added
- Introduce PHP_HIDE_X_POWERED_BY variable
## 7.5.2 2023-03-20
### Added
- Add gnu-libconv package
## 7.5.1 2023-03-16
### Changed
- Change log_errors_max_len to 0 in php.ini from 1024
### Reverted
- Strip php_admin_value[log_errors_max_len] from fpm config
## 7.5.0 2023-03-15
### Changed
- Quiet down output when loading defaults (xxx is already loaded! warnings)
- Rework initialization
- Fix a weird opcache issue
## 7.4.2 2023-02-21
### Changed
- Fix for LLNG_AUTHENTICATION_TYPE not reading variables properly
## 7.4.1 2023-01-16
### Changed
- Fix for 7.4.0
## 7.4.0 2023-01-15
### Added
- Add JIT Compilation support by means of PHP_OPCACHE_JIT_MODE and PHP_OPCACHE_BUFFER_SIZE variables (8.x only)
### Changed
- Minor formatting fixes
## 7.3.4 2023-01-11
### Changed
- Convert alias to function in php-ext for non interactive sessions
## 7.3.3 2023-01-10
### Changed
- Fix for `php-ext` not reading modules with underscores properly (credit timoschwarzer@github)
## 7.3.2 2022-12-14
### Changed
- Fix PHP_BASE issue with modules not loading introduced with 7.3.0
## 7.3.1 2022-12-13
### Changed
- Patchup for 8.2.x on Alpine systems
## 7.3.0 2022-12-11
### Added
- Introduce PHP 8.2 Support
### Changed
- Rework Dockerfiles
## 7.2.1 2022-11-23
### Changed
- Switch PHP 8.1 base to Alpine 3.17
## 7.2.0 2022-10-13
### Added
- Introduce customizable Opcache and APC environment variables
## 7.1.1 2022-10-05
### Changed
- Remvoe /var/log entries in Dockerfile build
## 7.1.0 2022-10-01
### Added
- Convert to using update_template functions when configuring
### Changed
- Fix an error where sample php file wasn't being created properly
## 7.0.11 2022-09-16
### Changed
- Change the way PHP_DISPLAY_ERRORS works in code - True / False actually works
## 7.0.10 2022-08-17
### Changed
- Switch to using exec to have process take over pid
## 7.0.9 2022-08-08
### Changed
- Additional fixes to 7.0.8
## 7.0.8 2022-08-08
### Changed
- Fix for Kitchen Sink mode showing pathnames on print_notice command
- Stop using log_length parameter for < PHP-FPM 7.3
## 7.0.7 2022-07-18
### Changed
- Fix for keepalives in upstream
## 7.0.6 2022-07-09
### Changed
- Escape document_root for FastCGI default scripts
## 7.0.5 2022-07-06
### Changed
- Fix for blank configuration not passing proper fastcgi_params
- Stop throwing an error for openssl if it doesn't exist in the slightest
## 7.0.4 2022-07-06
### Changed
- Debian: Switch to PHP_BASE versioned msgpack module
## 7.0.3 2022-07-05
### Changed
- Add ARG for easier build argument shifting with CI and command line
## 7.0.2 2022-07-04
### Changed
- Bugfix when there is no default.conf file available
## 7.0.1 2022-07-03
### Added
- Add PHP_FPM_OUTPUT_BUFFER_SIZE environment variable
## 7.0.0 2022-06-23
### Added
- Rewrote entire image and split into functions to be reused in descendent images
- Rework to support tiredofit/nginx:6.0.0 and its changes
### Changed
- Rename CONTAINER_MODE variable
- Quiet down output on extension loading/unloading
## 6.4.10 2022-05-24
### Added
- Alpine: Switch PHP 8 and 8.1 to Alpine 3.16 base
## 6.4.9 2022-04-12
### Changed
- Add support for debugging with PHPStorm
## 6.4.8 2022-04-11
### Changed
- Fix for open brace in if statement
- Revamp Xdebug options for PHP 7.2 and higher
## 6.4.7 2022-04-06
### Changed
- Adjust defaults to use proper if statements as opposed to shortcuts
## 6.4.6 2022-03-18
### Changed
- Fix for Debian images not including redis extension
## 6.4.5 2022-03-11
### Changed
- Sanity checks to be able to survive "warm" restarts
## 6.4.4 2022-03-08
### Added
- Remove php74-embed
## 6.4.3 2022-03-04
### Changed
- Change the way that upstream blocks are being added - stop relying on default.conf, instead put them in nginx.conf
## 6.4.2 2022-03-03
### Changed
- Patchup for 6.4.1
## 6.4.1 2022-03-02
### Added
- Add PHP_FPM_POST_INIT_SCRIPT variable to execute scripts before php-fpm process starts
- Add PHP_FPM_POST_INIT_COMMAND variable to execute command before php-fpm-process starts
## 6.4.0 2022-02-23
### Added
- Add multiple PHP upstream hosts by default
- Update LLNG Authentication to use Upstream Hosts
### Changed
- Code Cleanup, refactoring
## 6.3.7 2022-02-22
### Added
- Patchup Alpine Mono Dockerfile to properly build PHP 8.1 variants
## 6.3.6 2022-02-09
### Changed
- Fixes for builds showing up as PHP 8.1 instead of what they should be
- Base image updates
### Reverted
## 6.3.5 2021-12-28
### Changed
- Fixup for LibTidy throwing errors
## 6.3.4 2021-12-27
### Changed
- Fix for Zabbix Opcache monitoring
## 6.3.3 2021-12-16
### Changed
- Cleanup some of the autodiscover routines should Nginx or PHP-FPM be running in 'standalone' mode
## 6.3.2 2021-12-14
### Changed
- Fix for Docker Mono repo for PHP < 7.3 failing
## 6.3.1 2021-12-10
### Changed
- Fix for 6.3.0 Zabbix Templates and switch to User Parameters
## 6.3.0 2021-12-07
### Changed
- Rework Zabbix Monitoring scripts and templates
## 6.2.15 2021-12-01
### Changed
- Stop OpenSSL warning in PHP 8.1
## 6.2.14 2021-11-24
### Added
- Change PHP 7.4 and 8.0 to use Alpine 3.15 as base
## 6.2.13 2021-11-16
### Changed
- Fix for Zabbix PHP-FPM Metrics not functioning when AUTHENTICATION_TYPE=LLNG
## 6.2.12 2021-11-16
### Changed
- Fix for XDebug Log Path
## 6.2.11 2021-11-16
### Changed
- Adjustment to Log Level integer
## 6.2.10 2021-11-10
### Changed
- Change the way that access logs are being configured on startup for those who don't stop and destroy a container completely
## 6.2.9 2021-10-28
### Changed
- Debian: Fix for pulling in MariaDB repository
## 6.2.8 2021-10-28
### Changed
- Fix with pulling in MariaDB Repository
## 6.2.7 2021-10-20
### Added
- Add mariadb-connector-c to fix SHA2 problems with connecting to MariaDB 8.0 systems
## 6.2.6 2021-10-19
### Added
- Add PHP_LOG_LIMIT environment variable to ensure single line log levels in access/error.log
## 6.2.5 2021-09-04
### Changed
- Redo how logrotate files were created
## 6.2.4 2021-09-04
### Changed
- Opcache key removal for Zabbix monitoring
## 6.2.3 2021-09-04
### Changed
- Fix for monitoring PHP-FPM
## 6.2.2 2021-09-01
### Changed
- Fix for logformats
## 6.2.1 2021-09-01
### Changed
- Fix for msmtp not working due to a change in upstream base images
## 6.2.0 2021-08-29
### Added
- Added Access Log support with standard/default string output or json output
- Fluent-Bit Log Parsing support
## 6.1.21 2021-08-19
### Changed
- Change the way dependent modules are loaded in defaults
## 6.1.20 2021-08-18
### Changed
- Change to PECL http package
## 6.1.19 2021-08-18
### Changed
- Change to PHP Memcached plugin for debian
## 6.1.18 2021-08-05
### Added
- Add another value for socket timeout
- Cleanup some opcache console annoyances
## 6.1.17 2021-07-12
### Changed
- Move around some LLNG Authentication blocks
## 6.1.16 2021-07-05
### Added
- Support upstream image changes
## 6.1.15 2021-06-08
### Added
- Add Hook to load IGBINARY when PHP_ENABLE_MEMCACHED=TRUE
## 6.1.14 2021-06-04
### Added
- Enable APC Caching for CLI
## 6.1.13 2021-05-29
### Changed
- Final permissions fix for MSMTP
## 6.1.12 2021-05-25
### Changed
- Additional checks for msmtp usage - If ENABLE_SMTP=FALSE then don't execute permissions settings
## 6.1.11 2021-05-25
### Changed
- Change the way that LLNG authentication gets loaded
## 6.1.10 2021-05-24
### Changed
- Fix for 6.1.9 permissions
## 6.1.9 2021-05-24
### Changed
- Update msmtprc file with nginx user/group permissions to allow php-fpm to send
- Shuffle XDebug environment variables and configuraiton around
## 6.1.8 2021-05-19
### Added
- Add gpgme package (Alpine)
### Changed
- Fix for php-ext enable script to stop loading json if PHP > 8
- GPG extension loading fix
## 6.1.7 2021-05-05
### Changed
- Force OPENSSL extension to be activated by default to fix composer errors
## 6.1.6 2021-05-04
### Changed
- Fix for opcache being loaded twice in some scenarios
## 6.1.5 2021-05-03
### Changed
- Fix for enabling json warning under php8
## 6.1.4 2021-05-03
### Changed
- Fix for JSON for
### Changed
- Add PHP_ENABLE_SESSION=TRUE to defaults
- Set PHP_ENABLE_IGBINARY=TRUE when PHP_ENABLE_REDIS=TRUE
## 6.1.2 2021-05-01
### Changed
- Fixes to php extension script specifically under Alpine
## 6.1.1 2021-05-01
### Changed
- Fix for determining PHP version on runtime
## 6.1.0 2021-04-22
### Changed
- Unified Script for Alpine and Debian
- Merged all changes up to 6.xx into Alpine build
## 6.0.1 2021-04-16
### Changed
- Fix PHP Extension script
- Opcache seems to want to load twice for some reason, dirty hack enabled
- Composer wasn't installing properly
## 6.0.0 2021-04-16
### Added
- Merged Debian branches into one - Use Build Argument of PHP_BASE to build `7.3` `7.4` or `8.0`
- Composer 2.x
- Massively revamped module loading. Try `php-env` from the command line to enable, disable, see modules available per version
- Building for Stretch and Buster, ready for Bullseye
- Building and amd64, arm7, arm64
## 5.6.0 2020-10-26
### Added
- Add composer version declaration (pinning to 1.10.16)
## 5.5.3 2020-08-29
### Added
- Add ENABLE_PHP_FPM environment variable
## 5.5.2 2020-08-10
### Changed
- Fix to regex for LLNG Authentication
## 5.5.1 2020-07-16
### Changed
- Fix logrotate for PHP-FPM
## 5.5.0 2020-06-09
### Added
- Update to support tiredofit/debian 5.0.0 base image
## 5.4.1 2020-06-05
### Changed
- Move /etc/s6/services to /etc/services.d
## 5.4.0 2020-05-13
### Added
- PHP 7.3 - Debian Buster Variant
## 5.3.7 2020-04-21
### Changed
- Remove extra logrotate.d file added by packages
## 5.3.6 2020-04-21
### Changed
- Fix for PHP Plugins not enabling correctly
## 5.3.5 2020-04-18
### Added
- Update to support tiredofit/alpine 4.5.1 base image
## 5.3.4 2020-03-16
### Changed
- Change msmtp configuration
## 5.3.3 2020-03-04
### Added
- Update image to support new tiredofit/alpine:4.4.0 base image
## 5.3.1 2020-01-20
### Changed
- Change the way PHP XDebug is being called
## 5.3.0 2020-01-04
### Added
- Add new `CONTAINER_MODE` environment variable to allow standalone operation for load balancing
- Add new `PHP_WEBROOT` environment variable when `CONTAINER_MODE` set to `php-fpm`
## 5.2.2 2020-01-03
### Added
- ADD PHP_POST_MAX_SIZE environment variable
### Changed
- Cleanup with LLNG Authentication
- Properly assign PHP_UPLOAD_MAX_SIZE and PHP_POST_MAX_SIZE variables
## 5.2.0 2019-12-31
### Added
- Move defaults to /assets/functions files
### Changed
- Change warnings to notices
## 5.1.0 2019-12-29
### Added
- Update to support new tiredofit/alpine base image
## 5.0.4 2019-12-19
### Changed
- Change to LLNG Authentication Auto Configuration Routines
## 5.0.3 2019-12-18
### Changed
- Fixed error with display errors configuration
## 5.0.2 2019-12-18
### Changed
- Change to support dynamic webserver user/group
## 5.0.1 2019-12-04
### Changed
- Make MySQL Default Enabled
## 5.0.0 2019-12-04
### Added
- Reworked entire image
- Added many new variables
- Basing off of tiredofit/nginx
- Code Cleanup
## 4.4.2 2019-11-18
### Changed
- Update Nginx proxy temp location
## 4.4.1 2019-07-08
* Add tmp folder during startup to avoid bootloop
## 4.4 2019-06-19
* PHP 7.3
* Alpine 3.10
## 4.3 2019-03-03
* Move Alpine base to 3.9
## 4.2 2018-12-17
* Add Nginx tmp cache directory
## 4.1 2018-11-28
* Fix Timezone setting for php.ini
## 4.0.1 2018-11-19
* Update further LLNG
## 4.0 2018-04-28
* Ability to protect service via basic authentication or using LemonLDAP:NG Handlers
## 3.7 2018-04-22
* Tweak SMTP to always route through msmtp based on new Base Image Changes
## 3.6 2018-04-02
* Added MAINTENANCE environment variable to move system to maintenance mode. Also maintenance script (off/on/sleep 60) inside container.
## 2018-03-18 3.5
* Add `STAGE` variable to be passed to PHP for Development/Production Purposes
## 2018-02-20 3.4
* Add Reverse Proxy Detection
## 2018-02-14 3.3
* Remove Redundant Entrypoint
* Fix Paths for enabled php modules
## 2018-02-01 3.2
* Fix PHP Timezone Issue
* Add Zabbix Scripts
## 2017-11-30 edge-3.1
* Switched to Edge Base
## 2017-09-17 3.1
* Fix Issue with PHP XDebug
* Added Imagick Extension
## 2017-08-27 3.0
* Big change (in image size) due to adding all available PHP Extensions
* Debug Mode via XDebug set via Environment Variables
* All PHP Extensions able to be enabled of disabled via Environment Variables
## 2017-07-12 2.6
* Added Checking to wait to start services in sequence
## 2017-07-12 2.5
* Added Composer, memcached, and sqlite extensions
## 2017-07-06 2.4
* Added proper logging for php-fpm
## 2017-07-06 2.3
* Add PHP_TIMEOUT
## 2017-07-03 2.2
* Added Logrotate
## 2017-07-01 2.1
* Sanity Check and write initialization state to /tmp/.container/*service name
* Added MSMTP to take place of sendmail
## 2017-06-23 2.0
* s6.d Process Seperation
* PHP-FPM run as NGINX
* Nginx Zabbix Checks set to port 73
* Nginx Uses conf.d file for Loading Site
## 2017-05-29 1.3
* Tracking Alpine 3.4
* PHP 5.6
## 2017-04-07 1.2
* Rebase
## 2017-02-08 1.1
* Added mariadb-client
## 2017-02-08 1.0
* Initial Release
* Alpine:edge
* PHP7
* Zabbix
================================================
FILE: Containerfile
================================================
# SPDX-FileCopyrightText: © 2026 Nfrastack
#
# SPDX-License-Identifier: MIT
ARG BASE_IMAGE
FROM ${BASE_IMAGE}
LABEL \
org.opencontainers.image.title="Nginx PHP-FPM" \
org.opencontainers.image.description="PHP Interpreter w/Web server" \
org.opencontainers.image.url="https://hub.docker.com/r/nfrastack/nginx-php-fpm" \
org.opencontainers.image.documentation="https://github.com/nfrastack/container-nginx-php-fpm/blob/main/README.md" \
org.opencontainers.image.source="https://github.com/nfrastack/container-nginx-php-fpm.git" \
org.opencontainers.image.authors="Nfrastack " \
org.opencontainers.image.vendor="Nfrastack " \
org.opencontainers.image.licenses="MIT"
ARG \
PHP_BASE
ENV \
CONTAINER_ENABLE_MESSAGING=TRUE \
IMAGE_NAME="nfrastack/nginx-php-fpm" \
IMAGE_REPO_URL="https://github.com/nfrastack/container-nginx-php-fpm/"
COPY CHANGELOG.md /usr/src/container/CHANGELOG.md
COPY LICENSE /usr/src/container/LICENSE
COPY README.md /usr/src/container/README.md
RUN echo "" && \
BUILD_ENV=" \
10-nginx/NGINX_CREATE_SAMPLE_HTML=FALSE \
10-nginx/NGINX_INDEX_FILE=index.php \
20-php-fpm/PHP_MODULE_ENABLE_APCU=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_BCMATH=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_BZ2=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_CTYPE=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_CURL=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_DOM=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_EXIF=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_FILEINFO=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_GD=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_ICONV=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_IMAP=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_INTL=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_MBSTRING=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_MYSQLI=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_MYSQLND=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_OPCACHE=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_OPENSSL=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_PDO=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_PDO_MYSQL=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_PGSQL=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_PHAR=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_SESSION=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_SIMPLEXML=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_TOKENIZER=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_XML=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_XMLREADER=TRUE \
20-php-fpm/PHP_MODULE_ENABLE_XMLWRITER=TRUE \
20-php-fpm/PHPFPM_USER=[env:NGINX_USER] \
20-php-fpm/PHPFPM_GROUP=[env:NGINX_GROUP] \
" \
&& \
PHP_BUILD_DEPS_ALPINE=" \
build-base \
php${PHP_BASE/./}-dev \
" \
&& \
PHP_BUILD_DEPS_DEBIAN=" \
" \
&& \
PHP_RUN_DEPS_ALPINE=" \
mariadb-client \
mariadb-connector-c \
postgresql-client \
" \
&& \
PHP_8_5_RUN_DEPS_ALPINE=" \
gnu-libiconv \
mariadb-connector-c \
" && \
\
PHP_8_4_RUN_DEPS_ALPINE=" \
gnu-libiconv \
mariadb-connector-c \
" && \
\
PHP_8_3_RUN_DEPS_ALPINE=" \
gnu-libiconv \
mariadb-connector-c \
" && \
\
PHP_8_2_RUN_DEPS_ALPINE=" \
gnu-libiconv \
mariadb-connector-c \
" && \
\
PHP_8_1_RUN_DEPS_ALPINE=" \
gnu-libiconv \
mariadb-connector-c \
" && \
\
PHP_8_0_RUN_DEPS_ALPINE=" \
gnu-libiconv \
mariadb-connector-c \
" && \
\
PHP_7_4_RUN_DEPS_ALPINE=" \
mariadb-connector-c \
" && \
\
PHP_7_3_RUN_DEPS_ALPINE=" \
mariadb-connector-c \
" && \
\
PHP_7_2_RUN_DEPS_ALPINE=" \
" && \
\
PHP_7_1_RUN_DEPS_ALPINE=" \
" && \
\
PHP_7_0_RUN_DEPS_ALPINE=" \
" && \
\
PHP_5_6_RUN_DEPS_ALPINE=" \
" && \
\
PHP_RUN_DEPS_DEBIAN=" \
ca-certificates \
git \
mariadb-client \
php-pear \
postgresql-client \
" \
PHP_8_5_RUN_DEPS_DEBIAN=" \
" && \
\
PHP_8_4_RUN_DEPS_DEBIAN=" \
" && \
\
PHP_8_3_RUN_DEPS_DEBIAN=" \
" && \
\
PHP_8_2_RUN_DEPS_DEBIAN=" \
" && \
\
PHP_8_1_RUN_DEPS=_DEBIAN" \
" && \
\
PHP_8_0_RUN_DEPS_DEBIAN=" \
" && \
\
PHP_7_4_RUN_DEPS_DEBIAN=" \
" && \
\
PHP_7_3_RUN_DEPS_DEBIAN=" \
" && \
\
source /container/base/functions/container/build && \
container_build_log image && \
create_user php 9000 www-data && \
add_user_group php www-data && \
case "$(container_info distro)" in \
"alpine" ) \
case "${PHP_BASE}" in \
8.[1-9] ) \
export _php_folder="/etc/php${PHP_BASE/./}" ; \
export _php_version="${PHP_BASE/./}" ; \
export build_gnupg=true ; \
;; \
8.0 | * ) \
export _php_folder="/etc/php${PHP_BASE:0:1}" ; \
export _php_version="${PHP_BASE:0:1}" ; \
export build_gnupg=false ; \
;; \
esac \
;; \
"debian" ) \
export _php_version="${PHP_BASE}" ; \
export _php_folder="/etc/php/${PHP_BASE}" ; \
package repo add mariadb ; \
package repo add postgres ; \
package repo key https://packages.sury.org/php/apt.gpg suryphp.gpg ; \
package repo add suryphp "https://packages.sury.org/php/ $(cat /etc/os-release |grep "VERSION=" | awk 'NR>1{print $1}' RS='(' FS=')') main" suryphp.gpg ; \
;; \
esac ; \
package update && \
package upgrade && \
package install \
PHP_BUILD_DEPS \
PHP_${PHP_BASE/./_}_BUILD_DEPS \
PHP_RUN_DEPS \
PHP_${PHP_BASE/./_}_RUN_DEPS \
&& \
\
case "$(container_info distro)" in \
"alpine" ) \
package install $(apk search -q php${_php_version} | grep "^php${_php_version}" | sed -e "/-cgi/d" -e "/-apache2/d" -e "/-doc/d" -e "/-dbg/d") ; \
sed -i "s|;cgi.fix_pathinfo=1|cgi.fix_pathinfo=0|g" ${_php_folder}/php.ini ; \
;; \
"debian" ) \
package install $(apt-cache search php${_php_version} | awk '{print $1}' | sed -e "/-cgi/d" -e "/-dbgsym/d" -e "/-dev/d" -e "/-gmagick/d" -e "/libapache2-mod/d" -e "/-libvirt/d" -e "/-yac/d") ; \
sed -i "s|;cgi.fix_pathinfo=1|cgi.fix_pathinfo=0|g" ${_php_folder}/cli/php.ini ; \
;; \
esac ; \
\
if [ -f /usr/sbin/php-fpm"${_php_version}" ] ; then ln -sf /usr/sbin/php-fpm"${_php_version}" /usr/sbin/php-fpm ; fi ; \
if [ -f /usr/sbin/php-fpm"${PHP_BASE}" ] ; then ln -sf /usr/sbin/php-fpm"${PHP_BASE}" /usr/sbin/php-fpm ; fi ; \
if [ -f /usr/bin/pecl"${_php_version}" ] ; then ln -sf /usr/bin/pecl"${_php_version}" /usr/sbin/pecl; fi ; \
if [ -f /usr/bin/php"${_php_version}" ] ; then ln -sf /usr/bin/php"${_php_version}" /usr/sbin/php ; fi ; \
if [ -f /usr/bin/phpize"${_php_version}" ] ; then ln -sf /usr/bin/phpize"${_php_version}" /usr/sbin/phpize ; fi ; \
curl -sSLk https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \
\
rm -rf \
"${_php_folder}"/environment/* \
"${_php_folder}"/php-fpm.d/* \
"${_php_folder}"/pools.d/* \
&& \
\
if [ "${_php_version}" = "5" ] ; then echo "suhosin.executor.include.whitelist = phar" >> "${_php_folder}"/php.ini ; fi ; \
\
case "$(container_info distro)" in \
"alpine" ) \
#### Disabling any but core extensions - When using this image as a base for other images, you'll want to turn turn them on before running composer with the inverse of phpdisomd (phpenmod) to keep things clean
mkdir -p "${_php_folder}"/conf.available/ && \
for module in "${_php_folder}"/conf.d/*.ini; do \
if [ ! -L "${module}" ] ; then \
if [ "$(echo $(basename $module) | grep -c '^[0-9][0-9].*')" = "0" ] ; then \
mv "${module}" "$(dirname ${module})/20_$(basename ${module})" ; \
module="$(dirname ${module})/20_$(basename ${module})"; \
fi ; \
if ! grep -w -i -q ";priority" "$module"; then \
echo ";priority=$(basename $module .ini | cut -d _ -f1)" >> $module ; \
mv "${module}" "${_php_folder}"/conf.available/$(basename "${module}" .ini | cut -c 4-).ini; \
fi; \
fi; \
done; \
rm -rf "${_php_folder}"/conf.d/* ; \
sed -i "s|;priority=00|;priority=10|g" "${_php_folder}"/conf.available/opcache.ini ; \
php_env_modules_enabled="$(set -o posix; set | sort | grep "^PHP_MODULE_ENABLE_.*=" | grep -i TRUE | cut -d _ -f 4 | cut -d = -f 1 | tr [A-Z] [a-z])" ; \
for module in $php_env_modules_enabled ; do \
if [ -f "${_php_folder}"/conf.available/"${module}".ini ] ; then \
priority=$(cat "${_php_folder}"/conf.available/"${module}".ini | grep ";priority" | cut -d = -f2) ; \
ln -sf "${_php_folder}"/conf.available/"${module}".ini "${_php_folder}"/conf.d/"${priority}"-"${module}".ini ; \
fi ; \
done ; \
if [ "${_php_version}" != "8" ] ; then \
if [ -f "${_php_folder}"/conf.available/json.ini ] ; then \
priority=$(cat "${_php_folder}"/conf.available/json.ini | grep ";priority" | cut -d = -f2) ; \
ln -sf "${_php_folder}"/conf.available/json.ini "${_php_folder}"/conf.d/"${priority}"-json.ini ; \
fi ; \
fi ; \
;; \
"debian" ) \
update-alternatives --set php /usr/bin/php${PHP_BASE} ; \
for f in /etc/php/${PHP_BASE}/mods-available/*.ini; do phpdismod $(basename $f .ini); done; \
php_env_modules_enabled="$(set -o posix; set | sort | grep "^PHP_MODULE_ENABLE_.*=" | grep -i TRUE | cut -d _ -f 4 | cut -d = -f 1 | tr A-Z a-z)" ; \
for module in $php_env_modules_enabled ; do phpenmod ${module} ; done ; \
if [ "${PHP_BASE}" = "7.3" ] || [ "${PHP_BASE}" = "7.4" ]; then phpenmod json ; fi ; \
find /etc/php/ -mindepth 1 -maxdepth 1 -type d -not -name ${PHP_BASE} -exec rm -rf '{}' \; 2>/dev/null ; \
;; \
esac ; \
\
package remove \
PHP_BUILD_DEPS \
PHP_${PHP_BASE/./_}_BUILD_DEPS \
&& \
package cleanup && \
rm -rf \
/root/.composer
COPY rootfs /
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2026 Nfrastack
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# nfrastack/container-nginx-php-fpm
## About
This repository will build a [Nginx](https://www.nginx.org) w/[PHP-FPM](https://php.net) container image, suitable for serving PHP scripts, or utilizing as a base image for installing additional software.
* Tracking PHP 5.3-8.5
* Easily enable / disable extensions based on your use case
* Automatic Log rotation
* Composer Included
* XDebug capability
* Caching via APC, opcache
* Includes client libraries for [MariaDB](https://www.mariadb.org) and [Postgresql](https://www.postgresql.org)
* Multiple pool support
## Maintainer
* [Nfrastack](https://www.nfrastack.com)
## Table of Contents
* [About](#about)
* [Maintainer](#maintainer)
* [Table of Contents](#table-of-contents)
* [Installation](#installation)
* [Prebuilt Images](#prebuilt-images)
* [Quick Start](#quick-start)
* [Persistent Storage](#persistent-storage)
* [Configuration](#configuration)
* [Environment Variables](#environment-variables)
* [Base Images used](#base-images-used)
* [Core Configuration](#core-configuration)
* [Users and Groups](#users-and-groups)
* [Networking](#networking)
* [Maintenance](#maintenance)
* [Shell Access](#shell-access)
* [Support & Maintenance](#support--maintenance)
* [License](#license)
* [References](#references)
## Installation
### Prebuilt Images
Feature limited builds of the image are available on the [Github Container Registry](https://github.com/nfrastack/container-nginx-php-fpm/pkgs/container/container-nginx-php-fpm) and [Docker Hub](https://hub.docker.com/r/nfrastack/nginx-php-fpm).
To unlock advanced features, one must provide a code to be able to change specific environment variables from defaults. Support the development to gain access to a code.
To get access to the image use your container orchestrator to pull from the following locations:
```
ghcr.io/nfrastack/container-nginx-php-fpm:(image_tag)
docker.io/nfrastack/nginx-php-fpm:(image_tag)
```
Image tag syntax is:
`:---`
Example:
`ghcr.io/nfrastack/container-nginx-php-fpm:latest` or
`ghcr.io/nfrastack/container-nginx-php-fpm:1.0-8.4-debian_trixie`
* `latest` will be the most recent commit
* An optional `tag` may exist that matches the [CHANGELOG](CHANGELOG.md) - These are the safest
| PHP version | Alpine Base | Tag | Debian Base | Tag |
| ----------- | ----------- | -------------- | ----------- | ---------------------- |
| latest | edge | `:alpine-edge` | | |
| 8.5.x | 3.23 | `:8.5-alpine` | | |
| 8.4.x | 3.23 | `:8.4-alpine` | Trixie | `:8.4-debian` |
| | | | Bookworm | `:8.4-debian_bookworm` |
| 8.3.x | 3.23 | `:8.3-alpine` | Bookworm | `:8.3-debian_trixie` |
| | | | Trixie | `:8.3-debian` |
| 8.2.x | 3.22 | `:8.2-alpine` | Trixie | `:8.2-debian` |
| | | | Bookworm | `:8.2-debian_bookworm` |
| 8.1.x | 3.19 | `:8.1-alpine` | | |
| 8.0.x | 3.16 | `:8.0-alpine` | | |
Have a look at the container registries and see what tags are available.
#### Multi-Architecture Support
Images are built for `amd64` by default, with optional support for `arm64` and other architectures.
### Quick Start
* The quickest way to get started is using [docker-compose](https://docs.docker.com/compose/). See the examples folder for a working [compose.yml](examples/compose.yml) that can be modified for your use.
* Map [persistent storage](#persistent-storage) for access to configuration and data files for backup.
* Set various [environment variables](#environment-variables) to understand the capabilities of this image.
Refer to the nginx upstream readme for configuration. If you do not create any configuration files for the sites, a default PHP location block will be added to your site
```nginx
location ~ [^/]\.php(/|$) {
try_files $fastcgi_script_name =404; # Fail if script missing
{{php_upstream}};
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index {{php_index_file}};
{{fastcgi_params}};
}
```
{{php_upstream}} will get replaced on container start with your PHP POOL value, and {{fastcgi_params}} will get replaced with the location of your nginx fastcgi_params.
### Persistent Storage
The following directories/files should be mapped for persistent storage in order to utilize the container effectively.
| Directory | Description |
| --------------- | -------------------------- |
| `/www/html` | Root Directory |
| `/logs/php-fpm` | Nginx and php-fpm logfiles |
### Environment Variables
#### Base Images used
This image relies on a customized base image in order to work.
Be sure to view the following repositories to understand all the customizable options:
| Image | Description |
| ------------------------------------------------------- | --------------- |
| [OS Base](https://github.com/nfrastack/container-base/) | Base Image |
| [Nginx](https://github.com/nfrastack/container-nginx/) | Nginx Webserver |
Below is the complete list of available options that can be used to customize your installation.
* Variables showing an 'x' under the `Advanced` column can only be set if the containers advanced functionality is enabled.
#### Core Configuration
| Variable | Description | Default |
| ----------------------- | ----------------------------------- | ----------------------------------- |
| `ENABLE_PHP_FPM` | Enable PHP-FPM container mode | `TRUE` |
| `PHPFPM_CONTAINER_MODE` | Container mode for PHP-FPM | `nginx-php-fpm` |
| `PHP_CREATE_SAMPLE_PHP` | Create a sample PHP page on startup | `TRUE` |
| `PHP_HIDE_X_POWERED_BY` | Hide X-Powered-By header | `TRUE` |
| `PHP_KITCHENSINK` | Enable all PHP extensions | `FALSE` |
| `PHP_MEMORY_LIMIT` | PHP memory limit | `128M` |
| `PHP_POST_MAX_SIZE` | Maximum POST size | `2G` |
| `PHP_TIMEOUT` | Script execution timeout | `180` |
| `PHP_UPLOAD_MAX_SIZE` | Maximum upload size | `2G` |
| `PHP_WEBROOT` | Webroot directory | `/www/html` (or `${NGINX_WEBROOT}`) |
#### PHP Environment
| Variable | Description | Default |
| ------------------- | ------------------------ | -------------------------------------------------------------- |
| `PHPFPM_ENV_TEMP` | PHP-FPM temp directory | `/tmp` |
| `PHPFPM_ENV_TMP` | PHP-FPM tmp directory | `/tmp` |
| `PHPFPM_ENV_TMPDIR` | PHP-FPM tmpdir | `/tmp` |
| `PHPFPM_ENV_PATH` | PHP-FPM PATH environment | `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin` |
#### PHP Pools
You can define multiple PHP-FPM pools using environment variables. The default pool uses variables prefixed with `PHPFPM_POOL_DEFAULT_`. To add additional pools, use the pattern:
`PHPFPM_POOL__`
For example, to add a pool named `api`:
```env
PHPFPM_POOL_API_LISTEN_TYPE=tcp
PHPFPM_POOL_API_LISTEN_TCP_PORT=9001
PHPFPM_POOL_API_USER=www-data
PHPFPM_POOL_API_GROUP=www-data
```
Each pool will be configured in `/etc/php.../pools.d/.conf` inside the container.
If no pool is defined then a default `www` pool will be created with the following default settings
Default pool settings:
| Variable | Description | Default |
| --------------------------------------------- | ----------------------------------------------- | ----------------------------------- |
| `PHPFPM_POOL_DEFAULT_LISTEN_UNIX_GROUP` | Default UNIX group for pool | `${NGINX_GROUP}` |
| `PHPFPM_POOL_DEFAULT_LISTEN_UNIX_USER` | Default UNIX user for pool | `${NGINX_USER}` |
| `PHPFPM_POOL_DEFAULT_USER` | Default pool user | `${NGINX_USER}` |
| `PHPFPM_POOL_DEFAULT_GROUP` | Default pool group | `${NGINX_GROUP}` |
| `PHPFPM_POOL_DEFAULT_CATCH_WORKERS_OUTPUT` | Catch workers output | `true` |
| `PHPFPM_POOL_DEFAULT_ENABLE_LOG` | Enable pool logging | `TRUE` |
| `PHPFPM_POOL_DEFAULT_PING_PATH` | Pool ping path | `/ping` |
| `PHPFPM_POOL_DEFAULT_DISPLAY_ERRORS` | Display errors | `TRUE` |
| `PHPFPM_POOL_DEFAULT_LISTEN_IP` | Pool listen IP | `0.0.0.0` |
| `PHPFPM_POOL_DEFAULT_LISTEN_TYPE` | Pool listen type `unix` `tcp` `both` - See note | `unix` |
| `PHPFPM_POOL_DEFAULT_LISTEN_PORT` | Pool listen port | `9000` |
| `PHPFPM_POOL_DEFAULT_LISTEN_TCP_IP` | Pool listen TCP IP | `0.0.0.0` |
| `PHPFPM_POOL_DEFAULT_LISTEN_TCP_IP_ALLOWED` | Allowed TCP IPs | `127.0.0.1` |
| `PHPFPM_POOL_DEFAULT_LISTEN_TCP_PORT` | Pool listen TCP port | `9000` |
| `PHPFPM_POOL_DEFAULT_LISTEN_UNIX_SOCKET` | Pool UNIX socket | `/var/lib/php-fpm/run/default.sock` |
| `PHPFPM_POOL_DEFAULT_ENV` | Default pool environment variables | `PATH,TEMP,TMP,TMPDIR` |
| `PHPFPM_POOL_DEFAULT_LOG_ACCESS_FILE` | Pool access log file | `default-access.log` |
| `PHPFPM_POOL_DEFAULT_LOG_ACCESS_FORMAT` | Pool access log format | `default` |
| `PHPFPM_POOL_DEFAULT_LOG_PATH` | Pool log path | `/logs/php-fpm/` |
| `PHPFPM_POOL_DEFAULT_MAX_CHILDREN` | Max children | `75` |
| `PHPFPM_POOL_DEFAULT_MAX_INPUT_NESTING_LEVEL` | Max input nesting level | `256` |
| `PHPFPM_POOL_DEFAULT_MAX_INPUT_VARS` | Max input vars | `10000` |
| `PHPFPM_POOL_DEFAULT_MAX_REQUESTS` | Max requests | `0` |
| `PHPFPM_POOL_DEFAULT_MAX_SPARE_SERVERS` | Max spare servers | `3` |
| `PHPFPM_POOL_DEFAULT_MEMORY_LIMIT` | Pool memory limit | `${PHP_MEMORY_LIMIT}` |
| `PHPFPM_POOL_DEFAULT_MIN_SPARE_SERVERS` | Min spare servers | `1` |
| `PHPFPM_POOL_DEFAULT_OUTPUT_BUFFER_SIZE` | Output buffer size | `0` |
| `PHPFPM_POOL_DEFAULT_POST_MAX_SIZE` | Pool POST max size | `${PHP_POST_MAX_SIZE}` |
| `PHPFPM_POOL_DEFAULT_PROCESS_IDLE_TIMEOUT` | Process idle timeout | `10s` |
| `PHPFPM_POOL_DEFAULT_PROCESS_MANAGER` | Process manager | `dynamic` |
| `PHPFPM_POOL_DEFAULT_START_SERVERS` | Start servers | `2` |
| `PHPFPM_POOL_DEFAULT_STATUS_PATH` | Status path | `/php-fpm_status` |
| `PHPFPM_POOL_DEFAULT_TIMEOUT` | Pool timeout | `${PHP_TIMEOUT}` |
| `PHPFPM_POOL_DEFAULT_UPLOAD_MAX_SIZE` | Pool upload max size | `${PHP_UPLOAD_MAX_SIZE}` |
#### Listening on both Unix socket and TCP at once
PHP-FPM does not allow multiple `listen` directives in a single pool — each pool owns exactly one endpoint. To accept FastCGI on both a Unix socket and a TCP port simultaneously, set:
```yaml
- PHPFPM_POOL__LISTEN_TYPE=both
```
The image then writes two pool configs:
* Primary pool `[]` — listens on the Unix socket (using `PHPFPM_POOL__LISTEN_UNIX_*` variables). This is the pool the image's nginx upstream is wired to.
* Shadow pool `[-tcp]` — listens on TCP (using `PHPFPM_POOL__LISTEN_TCP_*` variables). Inherits the same process-manager, log, environment, override, and includes settings as the primary.
#### Logging
| Variable | Description | Default |
| ----------------------- | -------------- | ------------------- |
| `PHPFPM_LOG_ERROR_FILE` | Error log file | `error.log` |
| `PHPFPM_LOG_ERROR_PATH` | Error log path | `/var/log/php-fpm/` |
| `PHPFPM_LOG_LEVEL` | Log level | `notice` |
| `PHPFPM_LOG_LIMIT` | Log limit | `3072` |
### Modules
#### Enabling / Disabling Specific Modules
Enable extensions by using the PHP extension name ie redis as `PHP_MODULE_ENABLE_REDIS=TRUE`. Core extensions are enabled by default are:
| Parameter | Default |
| ----------------------------- | ------- |
| `PHP_MODULE_ENABLE_APCU` | `TRUE` |
| `PHP_MODULE_ENABLE_BCMATH` | `TRUE` |
| `PHP_MODULE_ENABLE_BZ2` | `TRUE` |
| `PHP_MODULE_ENABLE_CTYPE` | `TRUE` |
| `PHP_MODULE_ENABLE_CURL` | `TRUE` |
| `PHP_MODULE_ENABLE_DOM` | `TRUE` |
| `PHP_MODULE_ENABLE_EXIF` | `TRUE` |
| `PHP_MODULE_ENABLE_FILEINFO` | `TRUE` |
| `PHP_MODULE_ENABLE_GD` | `TRUE` |
| `PHP_MODULE_ENABLE_ICONV` | `TRUE` |
| `PHP_MODULE_ENABLE_IMAP` | `TRUE` |
| `PHP_MODULE_ENABLE_INTL` | `TRUE` |
| `PHP_MODULE_ENABLE_JSON` | `TRUE` |
| `PHP_MODULE_ENABLE_MBSTRING` | `TRUE` |
| `PHP_MODULE_ENABLE_MYSQLI` | `TRUE` |
| `PHP_MODULE_ENABLE_MYSQLND` | `TRUE` |
| `PHP_MODULE_ENABLE_OPCACHE` | `TRUE` |
| `PHP_MODULE_ENABLE_OPENSSL` | `TRUE` |
| `PHP_MODULE_ENABLE_PDO` | `TRUE` |
| `PHP_MODULE_ENABLE_PDO_MYSQL` | `TRUE` |
| `PHP_MODULE_ENABLE_PGSQL` | `TRUE` |
| `PHP_MODULE_ENABLE_PHAR` | `TRUE` |
| `PHP_MODULE_ENABLE_SESSION` | `TRUE` |
| `PHP_MODULE_ENABLE_SIMPLEXML` | `TRUE` |
| `PHP_MODULE_ENABLE_TOKENIZER` | `TRUE` |
| `PHP_MODULE_ENABLE_XML` | `TRUE` |
| `PHP_MODULE_ENABLE_XMLREADER` | `TRUE` |
| `PHP_MODULE_ENABLE_XMLWRITER` | `TRUE` |
To enable all modules in image use `PHP_KITCHENSINK=TRUE`. Head inside the image and see what extensions are available by typing `php-ext list all`
###### APCu Options
| Variable | Description | Default |
| ------------------------- | ----------------------- | ------- |
| `PHP_MODULE_APC_SHM_SIZE` | APCu shared memory size | `128M` |
| `PHP_MODULE_APC_TTL` | APCu time to live | `7200` |
###### OPCache Options
| Variable | Description | Default |
| -------------------------------------------- | ------------------------------- | ----------- |
| `PHP_MODULE_OPCACHE_MEM_SIZE` | Opcache memory size | `128` |
| `PHP_MODULE_OPCACHE_INTERNED_STRINGS_BUFFER` | Opcache interned strings buffer | `8` |
| `PHP_MODULE_OPCACHE_JIT_BUFFER_SIZE` | Opcache JIT buffer size | `50M` |
| `PHP_MODULE_OPCACHE_JIT_MODE` | Opcache JIT mode | `1255` |
| `PHP_MODULE_OPCACHE_MAX_ACCELERATED_FILES` | Opcache max accelerated files | `10000` |
| `PHP_MODULE_OPCACHE_MAX_FILE_SIZE` | Opcache max file size | `0` |
| `PHP_MODULE_OPCACHE_MAX_WASTED_PERCENTAGE` | Opcache max wasted percentage | `5` |
| `PHP_MODULE_OPCACHE_OPTIMIZATION_LEVEL` | Opcache optimization level | `0x7FFFBFF` |
| `PHP_MODULE_OPCACHE_REVALIDATE_FREQ` | Opcache revalidate frequency | `2` |
| `PHP_MODULE_OPCACHE_SAVE_COMMENTS` | Opcache save comments | `1` |
| `PHP_MODULE_OPCACHE_VALIDATE_TIMESTAMPS` | Opcache validate timestamps | `1` |
###### XDebug Options
To enable XDebug set `PHP_MODULE_ENABLE_XDEBUG=TRUE`. Visit the [PHP XDebug Documentation](https://xdebug.org/docs/all_settings#remote_connect_back) to understand what these options mean.
If you debug a PHP project in PHPStorm, you need to set server name using `PHP_IDE_CONFIG` to the same value as set in PHPStorm. Usual value is localhost, i.e. `PHP_IDE_CONFIG="serverName=localhost"`.
For Xdebug 2 (php <= 7.1) you should set:
| Parameter | Description | Default |
| ------------------------------------------- | ------------------------------------------ | --------------- |
| `PHP_MODULE_XDEBUG_PROFILER_PATH` | Xdebug profiler path | `/logs/xdebug/` |
| `PHP_MODULE_XDEBUG_PROFILER_ENABLE` | Enable Profiler | `0` |
| `PHP_MODULE_XDEBUG_PROFILER_ENABLE_TRIGGER` | Enable Profiler Trigger | `0` |
| `PHP_MODULE_XDEBUG_REMOTE_AUTOSTART` | Enable Autostarting as opposed to GET/POST | `1` |
| `PHP_MODULE_XDEBUG_REMOTE_CONNECT_BACK` | Enbable Connection Back | `0` |
| `PHP_MODULE_XDEBUG_REMOTE_ENABLE` | Enable Remote Debugging | `1` |
| `PHP_MODULE_XDEBUG_REMOTE_HANDLER` | XDebug Remote Handler | `dbgp` |
| `PHP_MODULE_XDEBUG_REMOTE_HOST` | Set this to your IP Address | `127.0.0.1` |
| `PHP_MODULE_XDEBUG_REMOTE_PORT` | XDebug Remote Port | `9090` |
* * *
For Xdebug 3 (php >= 7.2) you should set:
| Parameter | Description | Default |
| ---------------------------------------- | -------------------------------------------------------------------- | --------------- |
| `PHP_MODULE_XDEBUG_PROFILER_PATH` | Xdebug profiler path | `/logs/xdebug/` |
| `PHP_MODULE_XDEBUG_MODE` | This setting controls which Xdebug features are enabled. | `develop` |
| `PHP_MODULE_XDEBUG_START_WITH_REQUEST` | Enable Autostarting as opposed to GET/POST | `default` |
| `PHP_MODULE_XDEBUG_DISCOVER_CLIENT_HOST` | Xdebug will try to connect to the client that made the HTTP request. | `1` |
| `PHP_MODULE_XDEBUG_CLIENT_HOST` | Set this to your IP Address | `127.0.0.1` |
| `PHP_MODULE_XDEBUG_CLIENT_PORT` | XDebug Remote Port | `9003` |
###### Including operator-supplied config files
| Parameter | Description | Default |
| ----------------------------- | --------------------------------------------------------------------------------- | ------- |
| `PHPFPM_POOL__INCLUDES` | Comma-separated paths appended as `include = ` lines to the pool's `.conf`. | |
#### Routing an nginx site to a specific PHP pool
When configuring a site, the image picks which PHP pool to wire it to via this resolution chain:
1. `NGINX_SITE__PHP_UPSTREAM` - per-site override (highest priority)
2. `NGINX_PHP_UPSTREAM` - global default for all sites
3. `www` - hardcoded fallback if neither is set
The value is the pool name (e.g. `www`, `api` (or `www-tcp` to target the shadow generated by `LISTEN_TYPE=both`).
| Parameter | Description | Default |
| ------------------------------------ | ------------------------------------------------------------ | ------- |
| `NGINX_SITE__PHP_UPSTREAM` | Pool name this site's nginx config should `fastcgi_pass` to. | `www` |
| `NGINX_PHP_UPSTREAM` | Default pool name used when no per-site override is set. | `www` |
## Users and Groups
| Type | Name | ID |
| ----- | ---------- | ------ |
| User | `php` | `9000` |
| Group | `php` | `9000` |
| Group | `www-data` | `82` |
### Networking
| Port | Protocol | Description |
| ------ | -------- | ----------- |
| `9000` | tcp | PHP-FPM |
* * *
## Maintenance
### Shell Access
For debugging and maintenance, `bash` and `sh` are available in the container.
## Support & Maintenance
* For community help, tips, and community discussions, visit the [Discussions board](/discussions).
* For personalized support or a support agreement, see [Nfrastack Support](https://nfrastack.com/).
* To report bugs, submit a [Bug Report](issues/new). Usage questions will be closed as not-a-bug.
* Feature requests are welcome, but not guaranteed. For prioritized development, consider a support agreement.
* Updates are best-effort, with priority given to active production use and support agreements.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
================================================
FILE: examples/.gitignore
================================================
!compose.yml
================================================
FILE: examples/.gitkeep
================================================
================================================
FILE: examples/compose.yml
================================================
services:
npf-app:
image: docker.io/nfrastack/nginx-php-fpm/8.5-alpine
container_name: npf-app
labels:
- traefik.enable=true
- traefik.http.routers.npf.rule=Host(`npf.example.com`)
- traefik.http.services.npf.loadbalancer.server.port=80
volumes:
- ./data/:/www/html
- ./logs/:/logs
environment:
- TIMEZONE=America/Vancouver
networks:
- services
- proxy
restart: always
networks:
proxy:
external: true
services:
external: true
================================================
FILE: rootfs/container/data/nginx/templates/server/http-fastcgi_hide_header_xpowered.template
================================================
# SPDX-FileCopyrightText: © 2026 Nfrastack
#
# SPDX-License-Identifier: MIT
fastcgi_hide_header X-Powered-By;
================================================
FILE: rootfs/container/data/nginx/templates/site/location-php-block.template
================================================
# SPDX-FileCopyrightText: © 2026 Nfrastack
#
# SPDX-License-Identifier: MIT
location ~ [^/]\.php(/|$) {
try_files $fastcgi_script_name =404; # Fail if script missing
{{php_upstream}};
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index {{php_index_file}};
{{fastcgi_params}};
}
================================================
FILE: rootfs/container/data/php-fpm/cli/php.ini
================================================
; SPDX-FileCopyrightText: © 2026 Nfrastack
;
; SPDX-License-Identifier: MIT
[PHP]
engine = On
allow_url_fopen = On
allow_url_include = Off
asp_tags = Off
auto_append_file =
auto_globals_jit = On
auto_prepend_file =
cgi.discard_path = 1
cgi.fix_pathinfo=0
default_charset = "UTF-8"
default_mimetype = "text/html"
default_socket_timeout = 180
disable_classes =
disable_functions =
display_errors = Off
display_startup_errors = Off
doc_root =
enable_dl = Off
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
expose_php = On
file_uploads = On
html_errors = On
ignore_repeated_errors = Off
ignore_repeated_source = Off
implicit_flush = Off
log_errors = On
log_errors_max_len = 0
max_execution_time = 30
max_file_uploads = 20
max_input_time = 180
memory_limit = 128M
output_buffering = 4096
post_max_size = 2G
precision = 14
register_argc_argv = Off
report_memleaks = On
request_order = "GP"
serialize_precision = 17
short_open_tag = Off
track_errors = Off
unserialize_callback_func =
upload_max_filesize = 2G
user_dir =
variables_order = "GPCS"
zend.enable_gc = On
zlib.output_compression = Off
[CLI Server]
cli_server.color = On
[Date]
date.timezone = UTC
[filter]
[iconv]
[intl]
[sqlite3]
[Pcre]
[Pdo]
[Pdo_mysql]
pdo_mysql.cache_size = 2000
pdo_mysql.default_socket=
[Phar]
[mail function]
SMTP = localhost
smtp_port = 25
;sendmail_path =
mail.add_x_header = On
[SQL]
sql.safe_mode = Off
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[Interbase]
ibase.allow_persistent = 1
ibase.max_persistent = -1
ibase.max_links = -1
ibase.timestampformat = "%Y-%m-%d %H:%M:%S"
ibase.dateformat = "%Y-%m-%d"
ibase.timeformat = "%H:%M:%S"
[MySQL]
mysql.allow_local_infile = On
mysql.allow_persistent = On
mysql.cache_size = 2000
mysql.max_persistent = -1
mysql.max_links = -1
mysql.default_port =
mysql.default_socket =
mysql.default_host =
mysql.default_user =
mysql.default_password =
mysql.connect_timeout = 60
mysql.trace_mode = Off
[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.cache_size = 2000
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off
[OCI8]
[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
[Sybase-CT]
sybct.allow_persistent = On
sybct.max_persistent = -1
sybct.max_links = -1
sybct.min_server_severity = 10
sybct.min_client_severity = 10
[bcmath]
bcmath.scale = 0
[browscap]
[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 5
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
[MSSQL]
mssql.allow_persistent = On
mssql.max_persistent = -1
mssql.max_links = -1
mssql.min_error_severity = 10
mssql.min_message_severity = 10
mssql.compatibility_mode = Off
mssql.secure_connection = Off
[Assertion]
[COM]
[mbstring]
[gd]
[exif]
[Tidy]
tidy.clean_output = Off
[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
[sysvshm]
[ldap]
ldap.max_links = -1
[mcrypt]
[dba]
[opcache]
[curl]
[openssl]
================================================
FILE: rootfs/container/data/php-fpm/conf.available/apcu.ini
================================================
; SPDX-FileCopyrightText: © 2026 Nfrastack
;
; SPDX-License-Identifier: MIT
extension=apcu.so
apc.enabled=1
apc.shm_size=128M
apc.ttl=7200
apc.enable_cli=1
;priority=20
================================================
FILE: rootfs/container/data/php-fpm/conf.available/opcache.ini
================================================
; SPDX-FileCopyrightText: © 2026 Nfrastack
;
; SPDX-License-Identifier: MIT
zend_extension=opcache.so
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.max_wasted_percentage=5
opcache.validate_timestamps=1
opcache.revalidate_freq=2
opcache.save_comments=1
opcache.optimization_level=0x7FFFBFFF
opcache.max_file_size=0
opcache.jit_buffer_size=0
opcache.jit=1255
;priority=10
================================================
FILE: rootfs/container/data/php-fpm/fpm/default.logformat
================================================
; SPDX-FileCopyrightText: © 2026 Nfrastack
;
; SPDX-License-Identifier: MIT
access.format='%{%Y-%m-%dT%H:%M:%S%z}T %{HTTP_X_FORWARDED_FOR}e %R %u %s %m "%{REQUEST_URI}e" %{HTTP_X_REQUEST_ID}e %{SERVER_PROTOCOL}e %l "%{HTTP_REFERER}e" "%{HTTP_USER_AGENT}e" %M %C %d'
================================================
FILE: rootfs/container/data/php-fpm/fpm/json.logformat
================================================
; SPDX-FileCopyrightText: © 2026 Nfrastack
;
; SPDX-License-Identifier: MIT
access.format='{"time":"%{%Y-%m-%dT%H:%M:%S%z}T","remote_addr":"%{HTTP_X_FORWARDED_FOR}","client_ip":"%R","remote_user":"%u","status":"%s","request_method":"%m","request_uri":"%{REQUEST_URI}e","request_id":"%{HTTP_X_REQUEST_ID}e","server_protocol":"%{SERVER_PROTOCOL}e","body_bytes_sent":"%l","http_referrer":"%{HTTP_REFERER}e","http_user_agent":"%{HTTP_USER_AGENT}e","memory_usage":"%M","cpu_usage":"%C","duration":"%d"}'
================================================
FILE: rootfs/container/data/php-fpm/fpm/php.ini
================================================
; SPDX-FileCopyrightText: © 2026 Nfrastack
;
; SPDX-License-Identifier: MIT
[PHP]
engine = On
allow_url_fopen = On
allow_url_include = Off
asp_tags = Off
auto_append_file =
auto_globals_jit = On
auto_prepend_file =
cgi.discard_path = 1
cgi.fix_pathinfo=0
default_charset = "UTF-8"
default_mimetype = "text/html"
default_socket_timeout = 180
disable_classes =
disable_functions =
display_errors = Off
display_startup_errors = Off
doc_root =
enable_dl = Off
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
expose_php = On
file_uploads = On
html_errors = On
ignore_repeated_errors = Off
ignore_repeated_source = Off
implicit_flush = Off
log_errors = On
log_errors_max_len = 1024
max_execution_time = 30
max_file_uploads = 20
max_input_time = 180
memory_limit = 128M
output_buffering = 4096
post_max_size = 2G
precision = 14
register_argc_argv = Off
report_memleaks = On
request_order = "GP"
serialize_precision = 17
short_open_tag = Off
track_errors = Off
unserialize_callback_func =
upload_max_filesize = 2G
user_dir =
variables_order = "GPCS"
zend.enable_gc = On
zlib.output_compression = Off
[CLI Server]
cli_server.color = On
[Date]
date.timezone = UTC
[filter]
[iconv]
[intl]
[sqlite3]
[Pcre]
[Pdo]
[Pdo_mysql]
pdo_mysql.cache_size = 2000
pdo_mysql.default_socket=
[Phar]
[mail function]
SMTP = localhost
smtp_port = 25
;sendmail_path =
mail.add_x_header = On
[SQL]
sql.safe_mode = Off
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[Interbase]
ibase.allow_persistent = 1
ibase.max_persistent = -1
ibase.max_links = -1
ibase.timestampformat = "%Y-%m-%d %H:%M:%S"
ibase.dateformat = "%Y-%m-%d"
ibase.timeformat = "%H:%M:%S"
[MySQL]
mysql.allow_local_infile = On
mysql.allow_persistent = On
mysql.cache_size = 2000
mysql.max_persistent = -1
mysql.max_links = -1
mysql.default_port =
mysql.default_socket =
mysql.default_host =
mysql.default_user =
mysql.default_password =
mysql.connect_timeout = 60
mysql.trace_mode = Off
[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.cache_size = 2000
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off
[OCI8]
[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
[Sybase-CT]
sybct.allow_persistent = On
sybct.max_persistent = -1
sybct.max_links = -1
sybct.min_server_severity = 10
sybct.min_client_severity = 10
[bcmath]
bcmath.scale = 0
[browscap]
[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 5
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
[MSSQL]
mssql.allow_persistent = On
mssql.max_persistent = -1
mssql.max_links = -1
mssql.min_error_severity = 10
mssql.min_message_severity = 10
mssql.compatibility_mode = Off
mssql.secure_connection = Off
[Assertion]
[COM]
[mbstring]
[gd]
[exif]
[Tidy]
tidy.clean_output = Off
[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
[sysvshm]
[ldap]
ldap.max_links = -1
[mcrypt]
[dba]
[opcache]
[curl]
[openssl]
================================================
FILE: rootfs/container/data/php-fpm/opcache/opcache-settings.php
================================================
================================================
FILE: rootfs/container/data/php-fpm/opcache/opcache-status.php
================================================
================================================
FILE: rootfs/container/defaults/20-php-fpm
================================================
# SPDX-FileCopyrightText: © 2026 Nfrastack
#
# SPDX-License-Identifier: MIT
ENABLE_PHP_FPM=${ENABLE_PHP_FPM:-"TRUE"}
PHPFPM_CONTAINER_MODE=${PHPFPM_CONTAINER_MODE:-"nginx-php-fpm"}
PHP_VERSION="$(php -v 2>/dev/null | grep "^PHP " | head -n 1 | awk '{print $2}')"
PHP_BASE="${PHP_VERSION%.*}"
PHP_ENABLE_CREATE_SAMPLE_PHP=${PHP_ENABLE_CREATE_SAMPLE_PHP:-"TRUE"}
PHP_HIDE_X_POWERED_BY=${PHP_HIDE_X_POWERED_BY:-"TRUE"}
PHP_KITCHENSINK=${PHP_KITCHENSINK:-"FALSE"}
PHP_MEMORY_LIMIT=${PHP_MEMORY_LIMIT:-"128M"}
PHP_MODULE_APC_SHM_SIZE=${PHP_MODULE_APC_SHM_SIZE:-"128M"}
PHP_MODULE_APC_TTL=${PHP_MODULE_APC_TTL:-"7200"}
PHP_MODULE_OPCACHE_INTERNED_STRINGS_BUFFER=${PHP_MODULE_OPCACHE_INTERNED_STRINGS_BUFFER:-"8"}
PHP_MODULE_OPCACHE_JIT_BUFFER_SIZE=${PHP_MODULE_OPCACHE_JIT_BUFFER_SIZE:-"50M"}
PHP_MODULE_OPCACHE_JIT_MODE=${PHP_MODULE_OPCACHE_JIT_MODE:-"1255"}
PHP_MODULE_OPCACHE_MAX_ACCELERATED_FILES=${PHP_MODULE_OPCACHE_MAX_ACCELERATED_FILES:-"10000"}
PHP_MODULE_OPCACHE_MAX_FILE_SIZE=${PHP_MODULE_OPCACHE_MAX_FILE_SIZE:-"0"}
PHP_MODULE_OPCACHE_MAX_WASTED_PERCENTAGE=${PHP_MODULE_OPCACHE_MAX_WASTED_PERCENTAGE:-"5"}
PHP_MODULE_OPCACHE_MEM_SIZE=${PHP_MODULE_OPCACHE_MEM_SIZE:-"128"}
PHP_MODULE_OPCACHE_OPTIMIZATION_LEVEL=${PHP_MODULE_OPCACHE_OPTIMIZATION_LEVEL:-"0x7FFFBFF"}
PHP_MODULE_OPCACHE_REVALIDATE_FREQ=${PHP_MODULE_OPCACHE_REVALIDATE_FREQ:-"2"}
PHP_MODULE_OPCACHE_SAVE_COMMENTS=${PHP_MODULE_OPCACHE_SAVE_COMMENTS:-"1"}
PHP_MODULE_OPCACHE_VALIDATE_TIMESTAMPS=${PHP_MODULE_OPCACHE_VALIDATE_TIMESTAMPS:-"1"}
#Xdebug 2
PHP_MODULE_XDEBUG_PROFILER_PATH=${PHP_MODULE_XDEBUG_PROFILER_PATH:-"/logs/xdebug/"}
PHP_MODULE_XDEBUG_PROFILER_ENABLE=${PHP_MODULE_XDEBUG_PROFILER_ENABLE:-"0"}
PHP_MODULE_XDEBUG_PROFILER_ENABLE_TRIGGER=${PHP_MODULE_XDEBUG_PROFILER_ENABLE_TRIGGER:-"0"}
PHP_MODULE_XDEBUG_REMOTE_AUTOSTART=${PHP_MODULE_XDEBUG_REMOTE_AUTOSTART:-"1"}
PHP_MODULE_XDEBUG_REMOTE_CONNECT_BACK=${PHP_MODULE_XDEBUG_REMOTE_CONNECT_BACK:-"0"}
PHP_MODULE_XDEBUG_REMOTE_ENABLE=${PHP_MODULE_XDEBUG_REMOTE_ENABLE:-"1"}
PHP_MODULE_XDEBUG_REMOTE_HANDLER=${PHP_MODULE_XDEBUG_REMOTE_HANDLER:-"dbgp"}
PHP_MODULE_XDEBUG_REMOTE_HOST=${PHP_MODULE_XDEBUG_REMOTE_HOST:-"127.0.0.1"}
PHP_MODULE_XDEBUG_REMOTE_PORT=${PHP_MODULE_XDEBUG_REMOTE_PORT:-"9090"}
#Xdebug 3
PHP_MODULE_XDEBUG_MODE=${PHP_MODULE_XDEBUG_MODE:-"develop"}
PHP_MODULE_XDEBUG_START_WITH_REQUEST=${PHP_MODULE_XDEBUG_START_WITH_REQUEST:-"default"}
PHP_MODULE_XDEBUG_DISCOVER_CLIENT_HOST=${PHP_MODULE_XDEBUG_DISCOVER_CLIENT_HOST:-"default"}
PHP_MODULE_XDEBUG_CLIENT_HOST=${PHP_MODULE_XDEBUG_CLIENT_HOST:-"127.0.0.1"}
PHP_MODULE_XDEBUG_CLIENT_PORT=${PHP_MODULE_XDEBUG_CLIENT_PORT:-"9003"}
if [ "${PHP_BASE:0:1}" != "8" ] ; then
PHP_MODULE_ENABLE_JSON=TRUE
fi
if var_true "${PHP_MODULE_ENABLE_MEMCACHED}" || var_true "${PHP_MODULE_ENABLE_REDIS}"; then
PHP_MODULE_ENABLE_IGBINARY=TRUE
PHP_MODULE_ENABLE_MSGPACK=TRUE
fi
PHP_POST_MAX_SIZE=${PHP_POST_MAX_SIZE:-"2G"}
PHP_TIMEOUT=${PHP_TIMEOUT:-"180"}
PHP_UPLOAD_MAX_SIZE=${PHP_UPLOAD_MAX_SIZE:-"2G"}
if [ -f "/usr/sbin/unitd" ] ; then
PHP_WEBROOT=${PHP_WEBROOT:-"${UNIT_WEBROOT}"}
PHPFPM_POOL_DEFAULT_USER=${PHPFPM_POOL_DEFAULT_USER:-"${UNIT_USER}"}
PHPFPM_POOL_DEFAULT_GROUP=${PHPFPM_POOL_DEFAULT_GROUP:-"${UNIT_GROUP}"}
PHPFPM_POOL_DEFAULT_LISTEN_UNIX_GROUP=${PHPFPM_POOL_DEFAULT_LISTEN_UNIX_GROUP:-"${PHPFPM_GROUP}"}
PHPFPM_POOL_DEFAULT_LISTEN_UNIX_USER=${PHPFPM_POOL_DEFAULT_LISTEN_UNIX_USER:-"${PHPFPM_USER}"}
fi
if [ -f "/usr/sbin/nginx" ] ; then
PHP_WEBROOT=${PHP_WEBROOT:-"${NGINX_WEBROOT}"}
PHPFPM_USER=${PHPFPM_USER:-"php"}
PHPFPM_GROUP=${PHPFPM_GROUP:-"www-data"}
PHPFPM_POOL_DEFAULT_LISTEN_UNIX_GROUP=${PHPFPM_POOL_DEFAULT_LISTEN_UNIX_GROUP:-"${PHPFPM_GROUP}"}
PHPFPM_POOL_DEFAULT_LISTEN_UNIX_USER=${PHPFPM_POOL_DEFAULT_LISTEN_UNIX_USER:-"${PHPFPM_USER}"}
#PHPFPM_USER=${PHPFPM_USER:-"${NGINX_USER}"}
#PHPFPM_GROUP=${PHPFPM_GROUP:-"${NGINX_GROUP}"}
fi
PHPFPM_ENV_TEMP=${PHPFPM_ENV_TEMP:-"/tmp"}
PHPFPM_ENV_TMP=${PHPFPM_ENV_TMP:-"/tmp"}
PHPFPM_ENV_TMPDIR=${PHPFPM_ENV_TMPDIR:-"/tmp"}
PHPFPM_ENV_PATH=${PHPFPM_ENV_PATH:-"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}
PHPFPM_LOG_ERROR_FILE=${PHPFPM_LOG_ERROR_FILE:-"error.log"}
PHPFPM_LOG_ERROR_PATH=${PHPFPM_LOG_ERROR_PATH:-"/var/log/php-fpm/"}
PHPFPM_LOG_LEVEL=${PHPFPM_LOG_LEVEL:-"notice"}
PHPFPM_LOG_LIMIT=${PHPFPM_LOG_LIMIT:-"3072"}
PHPFPM_POOL_DEFAULT_CATCH_WORKERS_OUTPUT=${PHPFPM_POOL_DEFAULT_CATCH_WORKERS_OUTPUT-"true"}
PHPFPM_POOL_DEFAULT_ENABLE_LOG=${PHPFPM_POOL_DEFAULT_ENABLE_LOG:-"TRUE"}
PHPFPM_POOL_DEFAULT_PING_PATH=${PHPFPM_POOL_DEFAULT_PING_PATH-"/ping"}
PHPFPM_POOL_DEFAULT_DISPLAY_ERRORS=${PHPFPM_POOL_DEFAULT_DISPLAY_ERRORS-"TRUE"}
PHPFPM_POOL_DEFAULT_LISTEN_IP=${PHPFPM_POOL_DEFAULT_LISTEN_IP:-"0.0.0.0"}
PHPFPM_POOL_DEFAULT_LISTEN_TYPE=${PHPFPM_POOL_DEFAULT_LISTEN_TYPE:-"unix"}
PHPFPM_POOL_DEFAULT_LISTEN_PORT=${PHPFPM_POOL_DEFAULT_LISTEN_PORT:-"9000"}
PHPFPM_POOL_DEFAULT_LISTEN_TCP_IP=${PHPFPM_POOL_DEFAULT_LISTEN_TCP_IP:-"${PHPFPM_POOL_DEFAULT_LISTEN_IP}"}
PHPFPM_POOL_DEFAULT_LISTEN_TCP_IP_ALLOWED=${PHPFPM_POOL_DEFAULT_LISTEN_TCP_IP_ALLOWED:-"127.0.0.1"}
PHPFPM_POOL_DEFAULT_LISTEN_TCP_PORT=${PHPFPM_POOL_DEFAULT_LISTEN_TCP_PORT:-"${PHPFPM_POOL_DEFAULT_LISTEN_PORT}"}
PHPFPM_POOL_DEFAULT_LISTEN_UNIX_SOCKET=${PHPFPM_POOL_DEFAULT_LISTEN_UNIX_SOCKET:-"/var/lib/php-fpm/run/default.sock"}
PHPFPM_POOL_DEFAULT_ENV=${PHPFPM_POOL_DEFAULT_ENV:-"PATH,TEMP,TMP,TMPDIR"}
PHPFPM_POOL_DEFAULT_LOG_ACCESS_FILE=${PHPFPM_POOL_DEFAULT_LOG_ACCESS_FILE:-"default-access.log"}
PHPFPM_POOL_DEFAULT_LOG_ACCESS_FORMAT=${PHPFPM_POOL_DEFAULT_LOG_ACCESS_FORMAT:-"default"}
PHPFPM_POOL_DEFAULT_LOG_PATH=${PHPFPM_POOL_DEFAULT_LOG_PATH:-"/logs/php-fpm/"}
PHPFPM_POOL_DEFAULT_MAX_CHILDREN=${PHPFPM_MAX_CHILDREN:-"75"}
PHPFPM_POOL_DEFAULT_MAX_INPUT_NESTING_LEVEL=${PHPFPM_MAX_INPUT_NESTING_LEVEL:-"256"}
PHPFPM_POOL_DEFAULT_MAX_INPUT_VARS=${PHPFPM_MAX_INPUT_VARS:-"10000"}
PHPFPM_POOL_DEFAULT_MAX_REQUESTS=${PHPFPM_MAX_REQUESTS:-"0"}
PHPFPM_POOL_DEFAULT_MAX_SPARE_SERVERS=${PHPFPM_MAX_SPARE_SERVERS:-"3"}
PHPFPM_POOL_DEFAULT_MEMORY_LIMIT=${PHPFPM_MEMORY_LIMIT:-"${PHP_MEMORY_LIMIT}"}
PHPFPM_POOL_DEFAULT_MIN_SPARE_SERVERS=${PHPFPM_MIN_SPARE_SERVERS:-"1"}
PHPFPM_POOL_DEFAULT_OUTPUT_BUFFER_SIZE=${PHPFPM_OUTPUT_BUFFER_SIZE:-"0"}
PHPFPM_POOL_DEFAULT_POST_MAX_SIZE=${PHPFPM_POOL_POST_MAX_SIZE:-"${PHP_POST_MAX_SIZE}"}
PHPFPM_POOL_DEFAULT_PROCESS_IDLE_TIMEOUT=${PHPFPM_PROCESS_IDLE_TIMEOUT:-"10s"}
PHPFPM_POOL_DEFAULT_PROCESS_MANAGER=${PHPFPM_PROCESS_MANAGER:-"dynamic"}
PHPFPM_POOL_DEFAULT_START_SERVERS=${PHPFPM_START_SERVERS:-"2"}
PHPFPM_POOL_DEFAULT_STATUS_PATH=${PHPFPM_STATUS_PATH:-"/php-fpm_status"}
PHPFPM_POOL_DEFAULT_TIMEOUT=${PHPFPM_TIMEOUT:-"${PHP_TIMEOUT}"}
PHPFPM_POOL_DEFAULT_UPLOAD_MAX_SIZE=${PHPFPM_UPLOAD_MAX_SIZE:-"${PHP_UPLOAD_MAX_SIZE}"}
get_defaults_advanced
================================================
FILE: rootfs/container/defaults/_20-php-fpm/20-php-fpm
================================================
# SPDX-FileCopyrightText: © 2026 Nfrastack
#
# SPDX-License-Identifier: MIT
================================================
FILE: rootfs/container/defaults/_20-php-fpm/20-php-fpm.advanced
================================================
# SPDX-FileCopyrightText: © 2026 Nfrastack
#
# SPDX-License-Identifier: MIT
================================================
FILE: rootfs/container/functions/20-php-fpm
================================================
# SPDX-FileCopyrightText: © 2026 Nfrastack
#
# SPDX-License-Identifier: MIT
phpfpm_bootstrap() {
case "$(container_info distro)" in
alpine )
case "${PHP_BASE}" in
8*)
php_prefix="/etc/php${PHP_BASE/./}/"
;;
* )
php_prefix="/etc/php${PHP_VERSION%%.*}/"
;;
esac
;;
"debian" )
php_root="/etc/php/${PHP_BASE}/"
php_prefix="/etc/php/${PHP_BASE}/fpm/"
;;
esac
}
phpfpm_nginx_create_location_block() {
if [ -z "${1:-}" ]; then return 1; fi
local _sitename="${1}"
local _site_path="${2:-}"
if [ -z "${_site_path}" ]; then
if [ -f "${NGINX_CONFIG_PATH%/}/sites.enabled/${_sitename}.conf" ]; then
_site_path="${NGINX_CONFIG_PATH%/}/sites.enabled/${_sitename}.conf"
fi
fi
if [ -z "${_site_path}" ]; then
print_debug "[create_location_block/${_sitename}] No site path available, skipping"
return 0
fi
local site_location="${_site_path%.*}/location"
local template_src="/container/data/nginx/templates/site/location-php-block.template"
if [ ! -d "${site_location}" ] || dir_empty "${site_location}" || ! grep -qRniE '^[[:space:]]*location[[:space:]]+[^{}]*php[^{}]*[[:space:]]*\{' "${site_location}" 2>/dev/null ; then
if [ -f "${template_src}" ]; then
print_debug "[create_location_block/${_sitename}] Installing php location block into ${site_location}"
mkdir -p "${site_location}"
cp -a --remove-destination "${template_src}" "${site_location}/20-php_block.conf"
else
print_warn "[create_location_block/${_sitename}] Template ${template_src} not found"
fi
else
print_debug "[create_location_block/${_sitename}] Existing PHP location block found, skipping"
fi
}
phpfpm_nginx_server_configure_upstream() {
if [ -n "${1}" ]; then
local _upstream="${1}"
local _upstream_file="${NGINX_CONFIG_PATH%/}"/"${NGINX_CONFIG_FILE}".d/php-fpm/${_upstream,,}.conf
create_folder "$(dirname "${_upstream_file}")" "${NGINX_USER}:${NGINX_GROUP}" 755
write_file "${_upstream_file}":644 <_LISTEN_TYPE=both
# Create -tcp pool sharing all other options pm/log/env/override/inclues
_transform_phpfpmpool_variable "${1^^}" LISTEN_TYPE _pool_listen_type
if [ "${_pool_listen_type,,}" != "both" ]; then
return
fi
local _pool_lower="${1,,}"
local _primary_conf="${_phpfpm_pool_prefix}.conf"
local _shadow_conf="${php_prefix%/}/pools.d/${_pool_lower}-tcp.conf"
if [ ! -f "${_primary_conf}" ]; then
print_warn "[pool_shadow_tcp/${_pool_lower}] Primary pool .conf not found at '${_primary_conf}' - skipping shadow"
return
fi
# refuse to clobber an user created -tcp pool
if echo " ${phpfpm_pool_list} " | grep -qi -- " ${_pool_lower}-tcp " 2>/dev/null; then
print_warn "[pool_shadow_tcp/${_pool_lower}] An operator-defined '${_pool_lower}-tcp' pool exists - skipping shadow generation"
return
fi
_transform_phpfpmpool_variable "${1^^}" LISTEN_TCP_IP _shadow_tcp_ip
_transform_phpfpmpool_variable "${1^^}" LISTEN_TCP_PORT _shadow_tcp_port
_transform_phpfpmpool_variable "${1^^}" LISTEN_TCP_IP_ALLOWED _shadow_tcp_allowed
: "${_shadow_tcp_ip:=127.0.0.1}"
: "${_shadow_tcp_port:=9000}"
: "${_shadow_tcp_allowed:=127.0.0.1}"
local _shadow_pool="${_pool_lower}-tcp"
print_notice "[pool_shadow_tcp/${_pool_lower}] Spawning shadow pool '${_shadow_pool}' listening on ${_shadow_tcp_ip}:${_shadow_tcp_port}"
sed \
-e "s|^\[${_pool_lower}\]|[${_shadow_pool}]|" \
-e "\|^include[[:space:]]*=.*${_pool_lower}-listener\.conf$|d" \
"${_primary_conf}" > "${_shadow_conf}"
{
echo "listen = ${_shadow_tcp_ip}:${_shadow_tcp_port}"
echo "listen.allowed_clients = ${_shadow_tcp_allowed}"
} >> "${_shadow_conf}"
local _shadow_upstream_file="${NGINX_CONFIG_PATH%/}/${NGINX_CONFIG_FILE}.d/php-fpm/${_shadow_pool}.conf"
create_folder "$(dirname "${_shadow_upstream_file}")" "${NGINX_USER}:${NGINX_GROUP}" 755
write_file "${_shadow_upstream_file}":644 <
Default Page
Container is working
Congratulations! Your ${IMAGE_NAME} $(container_info distro) $(container_info variant) PHP-FPM image is working. You are seeing this because you don't have an index.php file in your ${PHP_WEBROOT} directory.
For more info visit https://www.nfrastack.com