From f3c65de9da639b09aaa30581e49f6f2b055e000f Mon Sep 17 00:00:00 2001 From: Elijah Duffy Date: Mon, 8 Dec 2025 19:26:15 -0800 Subject: [PATCH] php-fpm: refactor with deterministic config files & improved debug --- README.md | 9 +++++++++ php-fpm/7.4/Dockerfile | 24 +++++------------------- php-fpm/7.4/php-fpm.conf | 8 ++++++++ php-fpm/7.4/www.conf | 4 ++++ php-fpm/conf.d/40-opcache.ini | 7 +++++++ php-fpm/conf.d/90-runtime.ini | 5 +++++ php-fpm/conf.d/99-force-debug.ini | 1 + shared/php-fpm/entrypoint.sh | 23 +++++++++++++++-------- shared/php-fpm/force-debug.php | 25 +++++++++++++++++-------- 9 files changed, 71 insertions(+), 35 deletions(-) create mode 100644 php-fpm/7.4/php-fpm.conf create mode 100644 php-fpm/conf.d/40-opcache.ini create mode 100644 php-fpm/conf.d/90-runtime.ini create mode 100644 php-fpm/conf.d/99-force-debug.ini diff --git a/README.md b/README.md index fec321d..61160a0 100644 --- a/README.md +++ b/README.md @@ -31,12 +31,21 @@ The CI workflow is configured to build with the repository root as the Docker bu - Images use `/var/www/html` as the webroot. When you mount a host directory over that path the mount replaces the image contents, including ownership. - Recommended safe options: + - Pre-chown host files to UID/GID 1000 before starting containers: + ```bash sudo chown -R 1000:1000 ./wp_root ``` + - Or enable the entrypoint-based fixup in php-fpm by setting `CHOWN_ON_START=1` for the `php-fpm` service (the entrypoint is guarded — it only runs when this env is explicitly enabled). + ## Logging & debugging + + - PHP-FPM is configured to stream its master/process worker logs and PHP error log to stderr, so `docker compose logs php-fpm` (or your platform equivalent) will always contain fatal errors. + - When you need full stack traces in the browser, set `FORCE_DEBUG_ERRORS=1` on the `php-fpm` service. The shipped `force-debug.php` bootstrap will notice the flag, turn on verbose error reporting, and emit a single log line indicating that debug mode is active. + - Remove or unset `FORCE_DEBUG_ERRORS` after troubleshooting so production responses stay clean. + ## Local Testing & Development Use the provided `docker-compose.yml` in the repo root for local development — it builds images from the repo (so shared files are available) and mounts `./wp_root` for site content. diff --git a/php-fpm/7.4/Dockerfile b/php-fpm/7.4/Dockerfile index 8bfbe49..a13e649 100644 --- a/php-fpm/7.4/Dockerfile +++ b/php-fpm/7.4/Dockerfile @@ -79,30 +79,16 @@ RUN addgroup -g 1000 app && \ mkdir -p /var/run/php /run/php /var/log/php && \ chown -R app:app /var/run/php /run/php /var/log/php -# Minimal security / production tuning for opcache and PHP -RUN set -eux; \ - { \ - echo 'opcache.enable=1'; \ - echo 'opcache.memory_consumption=128'; \ - echo 'opcache.interned_strings_buffer=8'; \ - echo 'opcache.max_accelerated_files=10000'; \ - echo 'opcache.revalidate_freq=2'; \ - echo 'opcache.fast_shutdown=1'; \ - echo 'opcache.enable_file_override=0'; \ - } > /usr/local/etc/php/conf.d/zz-opcache.ini; \ - { \ - echo 'expose_php = Off'; \ - echo 'display_errors = On'; \ - echo 'log_errors = On'; \ - echo 'error_log = /proc/self/fd/2'; \ - } > /usr/local/etc/php/conf.d/zz-hardening.ini +# Ship opinionated PHP configuration snippets from source control +COPY php-fpm/conf.d/ /usr/local/etc/php/conf.d/ -# Copy the force-debug script and enable it +# Copy the force-debug script (enablement is handled via conf.d/99-force-debug.ini) COPY --chown=app:app shared/php-fpm/force-debug.php /usr/local/etc/php/force-debug.php -RUN echo 'auto_prepend_file = /usr/local/etc/php/force-debug.php' > /usr/local/etc/php/conf.d/zz-force-debug.ini # Copy pool configuration from this directory COPY --chown=app:app php-fpm/${BASE_VERSION}/www.conf /usr/local/etc/php-fpm.d/www.conf +# Copy the global php-fpm configuration so logging defaults are predictable +COPY php-fpm/${BASE_VERSION}/php-fpm.conf /usr/local/etc/php-fpm.conf # Copy entrypoint from shared path in repo root COPY --chown=root:root shared/php-fpm/entrypoint.sh /usr/local/bin/entrypoint.sh diff --git a/php-fpm/7.4/php-fpm.conf b/php-fpm/7.4/php-fpm.conf new file mode 100644 index 0000000..0b88ff6 --- /dev/null +++ b/php-fpm/7.4/php-fpm.conf @@ -0,0 +1,8 @@ +[global] +pid = /var/run/php/php-fpm.pid +error_log = /proc/self/fd/2 +log_limit = 8192 +log_buffering = no +daemonize = no + +include = /usr/local/etc/php-fpm.d/*.conf diff --git a/php-fpm/7.4/www.conf b/php-fpm/7.4/www.conf index 76906a7..9b96470 100644 --- a/php-fpm/7.4/www.conf +++ b/php-fpm/7.4/www.conf @@ -41,6 +41,10 @@ request_terminate_timeout = 300s request_slowlog_timeout = 5s slowlog = /var/log/php/www-slow.log +; Force all PHP errors into the container log stream so kubernetes/docker can collect them. +php_admin_flag[log_errors] = on +php_admin_value[error_log] = /proc/self/fd/2 + ; Redirect worker stdout and stderr to the main error log. ; This ensures that any `echo` or `var_dump` calls from workers are captured in the container logs. catch_workers_output = yes diff --git a/php-fpm/conf.d/40-opcache.ini b/php-fpm/conf.d/40-opcache.ini new file mode 100644 index 0000000..571bcdb --- /dev/null +++ b/php-fpm/conf.d/40-opcache.ini @@ -0,0 +1,7 @@ +opcache.enable=1 +opcache.memory_consumption=128 +opcache.interned_strings_buffer=8 +opcache.max_accelerated_files=10000 +opcache.revalidate_freq=2 +opcache.fast_shutdown=1 +opcache.enable_file_override=0 diff --git a/php-fpm/conf.d/90-runtime.ini b/php-fpm/conf.d/90-runtime.ini new file mode 100644 index 0000000..6332f10 --- /dev/null +++ b/php-fpm/conf.d/90-runtime.ini @@ -0,0 +1,5 @@ +expose_php=Off +log_errors=On +error_log=/proc/self/fd/2 +display_errors=Off +display_startup_errors=Off diff --git a/php-fpm/conf.d/99-force-debug.ini b/php-fpm/conf.d/99-force-debug.ini new file mode 100644 index 0000000..4bcf9c7 --- /dev/null +++ b/php-fpm/conf.d/99-force-debug.ini @@ -0,0 +1 @@ +auto_prepend_file=/usr/local/etc/php/force-debug.php diff --git a/shared/php-fpm/entrypoint.sh b/shared/php-fpm/entrypoint.sh index c1f419a..f9ac9dd 100644 --- a/shared/php-fpm/entrypoint.sh +++ b/shared/php-fpm/entrypoint.sh @@ -1,12 +1,19 @@ #!/bin/sh -set -euo pipefail +set -eu -: ${CHOWN_ON_START:=} -if [ "${CHOWN_ON_START}" = "1" ] || [ "${CHOWN_ON_START}" = "true" ]; then - echo "[entrypoint] CHOWN_ON_START enabled — fixing ownership of /var/www/html" - if [ -d /var/www/html ]; then - chown -R 1000:1000 /var/www/html || true - fi +PHP_ENTRYPOINT="/usr/local/bin/docker-php-entrypoint" +if [ ! -x "${PHP_ENTRYPOINT}" ]; then + echo "[entrypoint] Missing ${PHP_ENTRYPOINT}" >&2 + exit 1 fi -exec "$@" +case "${CHOWN_ON_START:-}" in + 1|true|TRUE|yes|on) + echo "[entrypoint] CHOWN_ON_START enabled — fixing ownership of /var/www/html" + if [ -d /var/www/html ]; then + chown -R 1000:1000 /var/www/html || true + fi + ;; +esac + +exec "${PHP_ENTRYPOINT}" "$@" diff --git a/shared/php-fpm/force-debug.php b/shared/php-fpm/force-debug.php index d4c13fb..46c8621 100644 --- a/shared/php-fpm/force-debug.php +++ b/shared/php-fpm/force-debug.php @@ -1,14 +1,23 @@ +ini_set('error_log', '/proc/self/fd/2'); + +error_log('[force-debug] Verbose error reporting enabled via FORCE_DEBUG_ERRORS');