Strip PHP runtime from buildComposerProject output

Hi there!

I’m trying to build two docker images: one with the PHP runtime and one with Caddy. Including the PHP project, which is being built using buildComposerProject, automatically includes the whole PHP runtime. This is fine for the PHP image, but I don’t really need it in the Caddy image.

Is there a way to just get the source files + vendor directory from $out? I’ve tried messing with the postInstall hook, but have had no success yet.

This is what I’m doing to build my project:

project = php-env.prod.buildComposerProject(finalAttrs: {
  pname = "symfonix";
  version = "1.0.0";
  src = ./..;
  vendorHash = "sha256-eNe0MYPOech3Vk5Wkp7zvR8orKE/AQ0A4jDu5hYNMPk=";

  frontend = pkgs.buildNpmPackage({
    inherit (finalAttrs) pname version src;
    npmDepsHash = "sha256-xk+bb5Pds7gYaxzCrVONjMaJ8ycoOgFsf+mc4WDUIYc=";
    nodejs = pkgs.nodejs_20;
    postInstall = ''
      cp -R public/build $out
    '';
  });

  postInstall = ''
    mkdir -p $out/share/php/symfonix/var/{cache,log}
    cd $out/share/php/symfonix
    composer dump-autoload --classmap-authoritative --no-dev
    composer dump-env prod
    composer run-script --no-dev post-install-cmd
    chmod +x bin/console
  '';
});

Any help would be greatly appreciated!

I figured it out! Copying the whole project drv into my Caddy image brought the PHP runtime along because there were scripts in de bin folder.

I really only need the public/ dir, copying that one alone works just fine.

Ultimately ended up using something like this:

publicFiles = (pkgs.runCommand "public" { } ''
    mkdir -p $out/share/php/symfonix
    cp -R ${project}/share/php/symfonix/public $out/share/php/symfonix/public
  '');

Cool, I might implement the idea at some point !
Glad the builder is useful!

I’ve been looking into this today and the only reason why PHP is included is because of SheBang patching.

To avoid including PHP in the derivation, just do:

  dontPatchShebangs = true;

Example with PHPUnit:

> nix path-info --recursive --size --closure-size --human-readable $(nix build --impure --print-out-paths --expr '(import ./. { system = "x86_64-linux";}).phpunit')
...
/nix/store/da9g3mhibah3vp16p0ssim5s690p6b1y-phpunit-11.1.1         5.6M  357.5M

With dontPatchShebangs = true;:

❯ nix path-info --recursive --size --closure-size --human-readable $(nix build --impure --print-out-paths --expr '(import ./. { system = "x86_64-linux";}).phpunit.overrideAttrs(oldAttrs: { dontPatchShebangs = true; })')
/nix/store/x7n0nzhir71cdh18hij501kcazss26fw-phpunit-11.1.1         5.6M   39.3M

Oh wow, that’s good to know! I could apply this and include the whole project dir tree in both of my container images, so that the layer is reused by docker (in theory) :sweat_smile: Neat!