GoogleCloudPlatform / buildpacks

Builders and buildpacks designed to run on Google Cloud's container platforms
Apache License 2.0
967 stars 144 forks source link

Option to have persistent folders inside tmp #315

Open sl0wik opened 1 year ago

sl0wik commented 1 year ago

Most of PHP frameworks including Laravel require writable paths to maintain various types of caches (view cache, bootstrap cache, application cache etc). Because the only writeable path is /tmp, multiple caching systems using the same folder cause conflict possibility and eventual security risk. If /tmp could have a persistent folder cache can be separated. It could be a single folder inside /tmp for example /tmp/build

Proposed solution: /tmp/build folder could be persistent from build to production run stage.

Impact: Developer can create a folder on build and then symlink for example /bootstrap/cache to /tmp/build/boostrap/cache maintaining complete framework compatibility without hackcs to change pre-set bootstrap cache paths to /tmp.

iamacarpet commented 1 year ago

@sl0wik is this for local development inside a Docker instance, or is this when deploying with Cloud Build?

I'm struggling to understand the use case for needing this to persist.

You mention bootstrap/cache with Laravel, which we struggled with when deploying to App Engine for production, so we made a php artisan gae:prepare command that pre-generates those cache files, and can be run from Cloud Build:

https://github.com/a1comms/GaeSupportLaravel/blob/php8.1-laravel9.x/src/A1comms/GaeSupportLaravel/Console/GaePrepareCommand.php#L72

https://github.com/a1comms/GaeSupportLaravel/blob/php8.1-laravel9.x/src/A1comms/GaeSupportLaravel/Foundation/ProviderRepository.php

Similarly for the view cache you mention, we made an artisan command to pre-compile all the views before deployment:

https://github.com/a1comms/GaeSupportLaravel/blob/php8.1-laravel9.x/src/A1comms/GaeSupportLaravel/Console/GaeViewCompileCommand.php

This meant that everything sits inside the storage folder and is deployed alongside the application, reducing the need for anything to end up in /tmp, except what we explicitly define as InstanceLocal cache:

https://github.com/a1comms/GaeSupportLaravel/blob/php8.1-laravel9.x/src/A1comms/GaeSupportLaravel/Cache/InstanceLocal.php

For more general application cache, storing to /tmp doesn't seem like a good fit, as in a multi-instance environment like App Engine or Cloud Run, your cache would be different on each instance, and you'd likely find they could end up serving different content, based on how fresh each cache was - so something like Redis / memcache is preferred.

sl0wik commented 1 year ago

@iamacarpet congrats for your package. I wish I checked it earlier.

The package vs separate Laravel-based project approach is the subject of a long discussion.

In general:

If we could simply have the option to create writeable folders, it would resolve majority of compatibility problems. It can be done today by symlinking but App would still need to make sure that folder exists in tmp.

Copying /tmp/build from build machine to production should be simple and would basically allow to run Laravel without CI.

sl0wik commented 1 year ago

Professional but more time-consuming solution would be adding to app.yaml option to set a writeable parameter that would contain a list of paths that should be writeable, for example:

writeable:
  - bootstrap/cache
  - storage

Build script could copy those directories to tmp/ and add symlinks. Normally I wouldn't trust tmp to store anything but it looks like App Engine currently using it to store files like nginx config.

sl0wik commented 1 year ago

I pushed changes to Laravel framework so the storage path can be overwritten using LARAVEL_STORAGE_PATH.