Skip to content

Add production-only mode when installing extensions for a PHP project #707

Description

@geangontijo

What are you trying to do?

Install only extensions required by production dependencies when building a production container image.

The project declares runtime extensions under require and Xdebug under require-dev:

{
  "require": {
    "ext-igbinary": "^3.2@RC",
    "ext-redis": "^6.3"
  },
  "require-dev": {
    "ext-xdebug": "^3.5"
  }
}

The image currently runs:

COPY composer.json composer.lock ./
RUN pie install --allow-non-interactive-project-install --auto-install-build-tools

This installs and enables Xdebug in the production image because project extension discovery includes root require-dev. Composer supports excluding development dependencies with --no-dev, but PIE has no equivalent project-install option.

What platform and PIE version are you using?

  • PIE 1.4.9 from ghcr.io/php/pie:bin
  • PHP 8.5
  • dunglas/frankenphp:1-php8-trixie builder
  • Linux ARM64 container build

Steps to reproduce

  1. Create the composer.json above.
  2. Run pie install --allow-non-interactive-project-install --auto-install-build-tools in a non-interactive container build.
  3. Run php -m or php -r 'var_dump(extension_loaded("xdebug"));'.
  4. Observe that Xdebug was installed and enabled despite being a development-only requirement.

What do you expect to happen?

PIE should provide a native production-only mode, for example:

pie install --no-dev

In that mode, project extension discovery should ignore root require-dev and extension requirements contributed only by development packages, while retaining the existing behavior by default.

What is actually happening?

InstallExtensionsForProjectCommand delegates to DetermineExtensionsRequired::forProject(), which unconditionally adds extension links from getDevRequires(). There is no CLI option to exclude them.

The available workarounds are to alter the Composer manifest during the image build or explicitly list every production extension package. Both duplicate dependency metadata and make future production extension additions easier to miss.

Impact

In our case, Xdebug 3.5.3 was enabled in develop mode in a production FrankenPHP image. A Laravel health endpoint dropped from roughly 100 ms to 9-10 ms when the same image was started with Xdebug disabled.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestmaintainer investigatingThis ticket is being investigated by maintainers. Please check with us before contributing PRs etc!

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions