brefphp / bref

Serverless PHP on AWS Lambda
https://bref.sh
MIT License
3.16k stars 365 forks source link

Imagick migrated to an external layer #743

Closed pleizi closed 3 years ago

pleizi commented 4 years ago

From today it has stopped working Imagick, I have updated my php.ini file but it hasn't worked. Then install bref/extra-php-extensions, following the documentation steps but it still doesn't work. Yesterday it worked without a problem, I don't know what happened.


Edit by @mnapoli:

Here is the official workaround: use the Bref extra imagick layer:

composer require bref/extra-php-extensions

Edit serverless.yml:

plugins:
    - ./vendor/bref/bref
    - ./vendor/bref/extra-php-extensions # <----- Add the extra Serverless plugin

functions:
    foo:
        # ...
        layers:
            - # ... existing layer
            - ${bref:extra.imagick-php-74} # <----- Include the imagick layer

Create a php/conf.d/php.ini file in your project:

extension=/opt/bref-extra/imagick.so
mnapoli commented 4 years ago

Hi, did you do something between yesterday and today? For example did you update Bref?

Could you detail what you mean by "it doesn't work"?

pleizi commented 4 years ago

No, I dont update bref, when I detected that Imagick Class stop working, I decided update Bref and install the new extra-php-extension, with the extra-bref-extension the Class work but it always throws me an error.

atrope commented 4 years ago

Hi, Our Extension also stopped working, from what i understood AWS updated the lambda underlying OS for custom runtimes and with that update it removed the old libs for imagick: You can see this post is from April: https://forum.directadmin.com/threads/cant-find-imagemagick-after-centos-update.61240

When i Run phpinfo on lambda the OS version is from May.

What i did was to build imagick from source in my machine and insert in the layers the needed libs and extension.

I Will attach here so you can create your layer yourself (this is for php 7.4 i don't know how it will behave with 7.2 or 7.3)

bref-imagick.zip

pleizi commented 4 years ago

I create the layer with your zip file but I continue with problems, the Imagick Class work, but when I run my code I get an error. "insufficient image data in file /tmp/magick-107D8EiVwQQJvw' @ error/jpeg.c/ReadJPEGImage/1156" or "improper image header/tmp/magick-1037Qq7TcwBDPL' @ error/png.c/ReadPNGImage/"

atrope commented 4 years ago

@pleizi maybe try with another image? Reading the error it looks like Maybe it's the image problem now?

pleizi commented 4 years ago

@pleizi maybe try with another image? Reading the error it looks like Maybe it's the image problem now?

I try with 10 images, the image is not the problem, I used the same images before the problem and they worked.

BenjaminRouge923 commented 4 years ago

Hi we have also the problem, any updates ? thanks

mnapoli commented 4 years ago

Hey thanks everyone for your comments, and thanks @atrope for the insight.

Could you all try out the extension in the https://github.com/brefphp/extra-php-extensions repository? In future Bref versions we will be extracting Imagick 100% in that repository, as a separate extension.

If that separate extension also fails, it should be easier to fix (I think). Here is the script that compiles the extension and extracts all the files needed by it: https://github.com/brefphp/extra-php-extensions/blob/master/layers/imagick/Dockerfile Maybe we should extract more files following the removal by AWS?

atrope commented 4 years ago

@mnapoli in my case those files were enough :)

mnapoli commented 4 years ago

OK that's good to know, thanks!

So here is the official workaround: use the Bref extra imagick layer:

composer require bref/extra-php-extensions

Edit serverless.yml:

plugins:
    - ./vendor/bref/bref
    - ./vendor/bref/extra-php-extensions # <----- Add the extra Serverless plugin

functions:
    foo:
        # ...
        layers:
            - # ... existing layer
            - ${bref:extra.imagick-php-74} # <----- Include the imagick layer

Create a php/conf.d/php.ini file in your project:

extension=/opt/bref-extra/imagick.so

Why not fix this in Bref?

At the moment, I think this might be best not to fix it in Bref. The reason is that it would mean adding extra system files in Bref, thus making the Bref layers heavier. That could make cold starts slower for existing projects, as well as possibly break deployment because they could hit the Lambda size limit.

I understand that this is trouble for some people, but considering that Imagick will not be included by default in Bref 1.0 (it will be available through the Bref Extra extension, as shown above), it doesn't sound too unreasonable to avoid that risk. Even though it means a bit of trouble for some users (sorry about that!), it's a change that was going to happen in 1.0 (coming soon).

Let's keep this issue open to gather feedback, but hopefully you understand the current stance.

yousaf-shah commented 4 years ago

I try with 10 images, the image is not the problem, I used the same images before the problem and they worked.

Hi everyone! We have the same problem. Imagick just stopped working a day or so ago. We've installed the extra PHP extensions as @mnapoli advised above and now although the imagick extension loads, we get the same file errors such as 'insufficient image data'. This is with files which are known OK and have worked prior to this - really need an answer for this if possible.

On another note - in our case we are getting dangerously close to the Lambda layer filesize limit. If the imagick code in the standard bref layer is now defunct (i.e. it will no longer work in Lambda) would it make sense to remove it ASAP? Just saying ... :)

victormacko commented 4 years ago

@yousaf-shah check here; https://bref.sh/docs/environment/performances.html#optimizing-cold-starts for ways to reduce your package size -- i've personally found there's a bunch of space taken up by fonts, docs, etc in the vendor directory which might help you out a bit.

patrickbussmann commented 4 years ago

Hmm I have the same issue but thanks to @mnapoli its fixed now. But now next problem: An error occurred: WebsiteLambdaFunction - Function code combined with layers exceeds the maximum allowed size of 262144000 bytes. The actual size is 278979951 bytes. (Service: AWSLambdaInternal; Status Code: 400; Error Code: InvalidParameterValueException; Request ID: e4c74da4-2e7c-4652-8dcb-d97898db2c03; Proxy: null).

The interesting thing is that I already removed 20 megabytes and it still show the same "actual size". So it seems to be the maximum and Bref PHP + Imagick is much higher than everything.

Is there a Bref PHP FPM without Imagick so that the extra layer not add it twice?

patrickbussmann commented 4 years ago

Now I excluded the whole vendor and cache folder and everything... The uploading ZIP file is only 1 MB of code. But still exceeding the size.

Serverless: Uploading service api.zip file to S3 (1.06 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
.......
Serverless: Operation failed!

  Serverless Error ---------------------------------------

  An error occurred: WebsiteLambdaFunction - Function code combined with layers exceeds the maximum allowed size of 262144000 bytes. The actual size is 278979951 bytes. (Service: AWSLambdaInternal; Status Code: 400; Error Code: InvalidParameterValueException; Request ID: a5aa178b-4caf-4fd1-8d13-2f56d8dd638e; Proxy: null).

When I delete ${bref:extra.imagick-php-74} from serverless.yml it works fine. hmmmm

mnapoli commented 4 years ago

That's weird, can anyone check the size of the imagick layer maybe? Maybe there's something broken in how it is constructed?

atrope commented 4 years ago

The zip I uploaded here and it is what works in my case unzipped has ~25MB (24,628,828 bytes) Those files/structure: Screen Shot 2020-09-18 at 11 39 25

patrickbussmann commented 4 years ago

@mnapoli @atrope: I created a very small test repository.

Thats working fine.

        layers:
            - ${bref:layer.php-74}
            - ${bref:extra.imagick-php-74}

Success:

Serverless: Stack update finished...

Thats not working.

        layers:
            - ${bref:layer.php-74-fpm}
            - ${bref:extra.imagick-php-74}

Error:

An error occurred: WebsiteLambdaFunction - Function code combined with layers exceeds the maximum allowed size of 262144000 bytes. The actual size is 275724672 bytes. (Service: Lambda, Status Code: 400, Request ID: 249368d2-ca64-4f81-8880-05b0d9e76928, Extended Request ID: null).

You can find it here: https://github.com/patrickbussmann/bref-imagick-too-big

I created two commits. First one working and latest one didn't.

mnapoli commented 4 years ago

The actual size is 275724672 bytes.

That's 262MB. The php-74-fpm layer is 113MB unzipped and the imagick layer is 38MB unzipped (I manually downloaded the latest versions to check).

That's 151MB. @patrickbussmann your test repository (after installing Composer dependencies) is 4MB (and even then you exclude vendor/, but let's ignore that). That's 155MB total, which is way below the limit. I don't understand why it's failing.


Wait, I cloned your repository and deployed: no problem for me. I managed to make it work correctly (had to enable the API Gateway). Not sure what's going on.

patrickbussmann commented 4 years ago

Wait, I cloned your repository and deployed: no problem for me. I managed to make it work correctly (had to enable the API Gateway). Not sure what's going on.

You must do composer install and npm install.

I found out that the issue is only with installed node_modules. But why?

I only did npm install serverless.

Without its working fine, too.

mnapoli commented 4 years ago

You are not supposed to deploy JS dependencies on Lambda: Lambda runs PHP, JS runs in the browser.

You should exclude node_modules/ from deployment.

OK I think there isn't any issue here.

patrickbussmann commented 4 years ago

My real project has it excluded and it still fails.

Calculation makes no sense.

That's 151MB

So and Windows shows me the unzipped from S3:

Amazon S3/project-dev-serverlessdeploymentbucket-3spbutp20duf/serverless/project/dev/1600682857646-2020-09-21T10:07:37.646Z/project.zip

Size: 28.6 MB

image (Grâße = Size, Inhalt = Content, Ordner = Directory, Datei = File)

So in worst case: 151 MB from layers + 99,5 MB size on disk = 250,5 MB

Error message: Function code combined with layers exceeds the maximum allowed size of 262144000 bytes. The actual size is 278979951 bytes.

The very bad thing is that even when I exclude everything I get this. Function code combined with layers exceeds the maximum allowed size of 262144000 bytes. The actual size is 278979951 bytes.

Thats with this serverless.yml:

package:
    exclude:
        - '.idea/**'
        - node_modules/**
        - tests/**
        - build/**
        - dist/**
        - public/bundles/**
        - ws/**
        - cache/**
        - vendor/**

The ZIP file on amazon is only 3 MB. Uploading service project.zip file to S3 (3.01 MB)...

What can I try? πŸ˜₯

patrickbussmann commented 4 years ago

Oh whats that. I deploy it to a new project and then its updating fine. But when I change it back its still not working.

Are there some cached files on the project side which I didnt see? Because everything is the same except the service: name in the top of the serverless.yml.

Old = Not working New = Working

😫

Do you have an idea? @mnapoli I will debug it today until I found the issue πŸ˜…

victormacko commented 4 years ago

Are you using Symfony? ... if so, did you forgot to exclude /var/cache/ and /var/log/ ? You could prob also exclude any assets directory which was originally used to build the 'build' dir.

patrickbussmann commented 4 years ago

Yes @victormacko but I already excluded it.

I found the solution! πŸ₯³ But its not really an solution. Its more an hacky debugging way and then its working at the end. I have a few build steps:

npm install
npm run compile
composer install --prefer-dist --optimize-autoloader --no-dev --no-interaction
php bin/console --env=prod assets:install public
php bin/console cache:clear --no-debug --no-warmup --env=prod
php bin/console cache:warmup --env=prod

I commented out all of those. Then I deployed each time. And after everything is commented back its working fine.

Maybe.... Maybe its an issue from the CI system which cached some things. (I mean its docker and no cache is set up) But I cant explain it.

I restored the whole serverless.yml. The .zip file is still 30 MB, unzipped it show 90 MB. (+ 150 MB from PHP-FPM + Imagick = 240 MB)

But its working now and hopefully not breaking again "somehow". Then I will make a documentation about each step so that I have more clear overview about whats going wrong.

Many thanks to you @mnapoli πŸ₯³

mnapoli commented 4 years ago

@patrickbussmann πŸ‘ I advise to download the code archive deployed by serverless.yml (from the S3 bucket) and unzip it: you can immediately see what shouldn't be there and exclude it from the next deployment.

Anyway, not related to imagick so that's good.

Yop-La commented 3 years ago

I also get the same issue. I tried many things.

And what worked for me was deploying that first:

Then deploy this:

I don't know why, the fact of having deployed a php image without fpm first allowed me to deploy then the php image with fpm whereas before I had the size limit error.

Weird. But anyway, now it's working fine πŸ‘Œ