Open peco8 opened 3 years ago
If my understanding is correct this problem is caused by creating a symlink of the vendor directory during the build process and ends up with autoloading failure.
Out of curiosity, why do you suspect the symlink is an issue? It seems to be loading other files from there OK. Where is that class expected to live?
Also, have you tried using HTTPD as the web server? The default will be PHP's built-in server. Some frameworks expect HTTPD because they include .htaccess
files that have required additional configuration.
https://paketo.io/docs/buildpacks/language-family-buildpacks/php/#web-server-configuration
Disregard that. I was able to reproduce and get this error:
[Sat Apr 24 17:24:40 2021] PHP 7.4.16 Development Server (http://0.0.0.0:8080) started
[Sat Apr 24 17:24:46 2021] 172.17.0.1:58460 Accepted
[Sat Apr 24 17:24:46 2021] PHP Warning: include(/layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/composer/../../app/Http/Kernel.php): failed to open stream: No such file or directory in /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/composer/ClassLoader.php on line 478
[Sat Apr 24 17:24:46 2021] PHP Warning: include(): Failed opening '/layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/composer/../../app/Http/Kernel.php' for inclusion (include_path='/layers/paketo-buildpacks_php-dist/php/lib/php:/workspace/.') in /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/composer/ClassLoader.php on line 478
[Sat Apr 24 17:24:46 2021] PHP Fatal error: Uncaught ReflectionException: Class App\Http\Kernel does not exist in /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php:833
Stack trace:
#0 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php(833): ReflectionClass->__construct('App\\Http\\Kernel')
#1 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php(714): Illuminate\Container\Container->build('App\\Http\\Kernel')
#2 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(841): Illuminate\Container\Container->resolve('App\\Http\\Kernel', Array, false)
#3 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php(284): Illuminate\Foundation\Application->resolve('App\\Http\\Kernel', Array, false)
#4 /layers/ in /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php on line 835
[Sat Apr 24 17:24:46 2021] 172.17.0.1:58460 [500]: GET / - Uncaught ReflectionException: Class App\Http\Kernel does not exist in /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php:833
Stack trace:
#0 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php(833): ReflectionClass->__construct('App\\Http\\Kernel')
#1 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php(714): Illuminate\Container\Container->build('App\\Http\\Kernel')
#2 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(841): Illuminate\Container\Container->resolve('App\\Http\\Kernel', Array, false)
#3 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php(284): Illuminate\Foundation\Application->resolve('App\\Http\\Kernel', Array, false)
#4 /layers/ in /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php on line 835
which looks like something is trying to load the file with a relative path, but that path doesn't exist there because things are relative from the symlink not from the /workspace/vendor
directory. Specifically, it's trying /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/composer/../../app/Http/Kernel.php
, but that should be /workspace/vendor/composer/../../app/Http/Kernel.php
.
So there is a fragile, but pretty easy way to make this work. You can symlink back to the app directory.
If you add a file called .profile
to the root of your application, and put this in it, that symlink will be created.
#!/bin/bash
ln -s /workspace/app /layers/paketo-buildpacks_php-composer/php-composer-packages/app
If you hit other similar issues, just keep adding symlinks in the same way so that PHP can find what it needs.
Unrelated note: to run your demo app, I also needed to add the openssl.so
extension. It should have been auto-detected as required by the buildpack. I believe that is a bug. File here -> https://github.com/paketo-buildpacks/php-composer/issues/190.
Some notes on this...
vendor
directory to exist in the context of the application folder, which is /workspace
within the container. We cannot just install composer dependencies there though because the app files are not cached from build to build. This would mean you'd need to install everything on every run, which would be slow and a bad experience. Instead, we install to a cached layer and symlink from the app directory to the layer.__FILE__
or __DIR__
to require
/ include
other code. That is supposed to give a link to the current directory, then you can use a relative location to load your other code. The behavior of these seems to resolve the symlink, which is why it's pulling in the path to the layer, not the app. However, the app's author has assumed the vendor directory will live alongside the app which is why it can't find the files, they don't exist in the layer./workspace
, we make a symlink from the layer directory where we store the vendor directory back to the app file. This is exactly what I'm doing in the workaround script above, it's just that the buildpack would automate it and doing it in a less fragile way. I think we need to recreate these on every build too, because the contents of the /workspace
can change on every build. That said, I think the overhead of creating some symlinks is less than copying a ton of files.@dmikusa-pivotal Hello from cf-for-k8s. I have a user facing issues with a Laravel app built with the PHP buildpack via Kpack. When I try to follow the same steps, I get 500 codes when trying to visit the /
path.
manifest.yml
---
applications:
- name: laravel
memory: 100M
buildpack: paketo-buildpacks/php
env:
APP_DEBUG: false
CF_STAGING_TIMEOUT: 15
CF_STARTUP_TIMEOUT: 15
buildpack.yml
composer:
vendor_directory: vendor
php:
# directory where web app code is stored
# default: htdocs
webdirectory: public
I add the .profile file you mentioned.
While Kpack might not be your area of expertise, it is still using Paketo Buildpacks to construct the application image, so I was hoping you'd have some thoughts.
@Birdrock what do you see in the server logs when the 500 happens? It should tell you why it's complaining.
The .profile
script hack above should work, at least it did for the sample app I used. An actual app might be more complicated, possibly more symlinks to create so everything can be loaded. The server logs should tell us what's happening. You might also want to put in something like echo 'Profile script running'
just so you can confirm that the script is getting picked up. You should then see that in the app logs prior to the server starting up.
Hope that helps!
Hi @dmikusa-pivotal,
I should have followed the link to the bug you reported. the missing OpenSSL extension seems to have been the problem. Thanks for the followup!
@paketo-buildpacks/php-maintainers This has been open for a while. Is there a need for a better solution than the workaround @dmikusa-pivotal offered? Would this problem be easier to fix after the PHP buildpack is restructured?
Hello, I'm trying to build Llaravel 8 with php buildpacks. Here is the step.
buildpack.yml
Here is the log when I acess
localhsot:8080
If my understanding is correct this problem is caused by creating a symlink of the vendor directory during the build process and ends up with autoloading failure. It would be great if you can look into this.