Skip to content

fix: restore PHP upload limits and OPcache tuning in the production image - #3

Merged
DGINXREAL merged 1 commit into
mainfrom
fix/production-php-limits
Aug 4, 2026
Merged

fix: restore PHP upload limits and OPcache tuning in the production image#3
DGINXREAL merged 1 commit into
mainfrom
fix/production-php-limits

Conversation

@theRomanOak

Copy link
Copy Markdown
Collaborator

Problem

The FrankenPHP base image loads no php.ini at all — neither php.ini-production nor php.ini-development — so PHP's built-in defaults apply. Verifiable against the base image:

docker run --rm dunglas/frankenphp:1-php8.4 \
    php -r 'echo ini_get("upload_max_filesize"), " ", php_ini_loaded_file() ?: "none";'
# -> 2M none

The application accepts vehicle documents up to 25 MB (VehicleDocumentsRelationManager::MAX_FILE_SIZE_KB) and images up to 10 MB (VehicleForm::MAX_IMAGE_SIZE_KB). In the published image every upload above 2 MB fails — and it fails before reaching the application's own validation, with a message that does not name the size as the cause ("field is required" instead of a statement about size).

42f923d intended to fold these limits into the image when it removed docker/uploads-prod.ini and docker/opcache-prod.ini, but no ini settings made it into the Dockerfile.

Change

Both files return as a single docker/php-prod.ini, copied to /usr/local/etc/php/conf.d/zz-app-prod.ini. The zz- prefix makes it load last, so the OPcache values win over docker-php-ext-opcache.ini from the base image.

  • Upload limitsupload_max_filesize=30M, post_max_size=32M (must exceed the file limit: it covers the whole form body, not just the file)
  • OPcache — memory, file count and interned-strings buffer tuned. validate_timestamps deliberately stays at its default, so a new image always serves current code without an extra cache-busting step.
  • display_errors=Off, expose_php=Off — Laravel switches display_errors off itself, but only once the framework is booted; an error before that (a missing extension, say) would otherwise reach the browser with paths and source lines.

CLAUDE.md documented docker/uploads-prod.ini as layer 1 of the three upload limits; that reference now points at the new file and explains why the setting is needed at all.

Verification

Values read out of the built image, not the source file:

Setting Value
upload_max_filesize 30M
post_max_size 32M
opcache.memory_consumption 256
opcache.max_accelerated_files 20000
display_errors off
expose_php off

Full suite: 383 passed (1222 assertions). Pint clean.

🤖 Generated with Claude Code

…mage

The FrankenPHP base image loads no php.ini at all — neither
php.ini-production nor php.ini-development — so PHP's built-in defaults
apply. Verifiable in the base image:

    docker run --rm dunglas/frankenphp:1-php8.4 \
        php -r 'echo ini_get("upload_max_filesize"), " ",
                     php_ini_loaded_file() ?: "none";'
    -> 2M none

The application accepts vehicle documents up to 25 MB and images up to
10 MB, so every upload above 2 MB failed in the published image — and
failed before reaching the application's own validation, with a message
that does not name the size as the cause.

42f923d intended to fold these limits into the image when it removed
docker/uploads-prod.ini and docker/opcache-prod.ini, but no ini settings
made it into the Dockerfile. This restores both as a single
docker/php-prod.ini copied to /usr/local/etc/php/conf.d/, prefixed zz-
so the OPcache values win over docker-php-ext-opcache.ini.

Also sets display_errors=Off and expose_php=Off: Laravel switches
display_errors off itself, but only once the framework is booted — an
error before that would reach the browser with paths and source lines.

Verified in the built image: upload_max_filesize=30M, post_max_size=32M,
opcache.memory_consumption=256, display_errors and expose_php off.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@DGINXREAL
DGINXREAL merged commit efd7d51 into main Aug 4, 2026
3 checks passed
@DGINXREAL
DGINXREAL deleted the fix/production-php-limits branch August 4, 2026 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants