11
votes

When attempting to run sharp inside an AWS Lambda function, I keep getting the following error:

darwin-x64' binaries cannot be used on the 'linux-x64' platform. Please remove the 'node_modules/sharp/vendor' directory and run 'npm install'

I deploy my serverless applications with Serverless Framework from my MacBook Pro. How do I fix this problem?

6
You need to build in a Linux environment as it is different from a Mac O/S environment. - stdunbar
I believe you're right. But how do I do that? And why is sharp environment dependent? - Keith Harris
There are multiple ways to do that. From a Mac O/S environment you may consider installing VirtualBox and then putting a Linux distribution there. Or, if you've already got an AWS account then you could spin up a small EC2 with Linux. That would require a dev environment in either environment. And it appears that Sharp has some native components under the hood. - stdunbar

6 Answers

22
votes

Kudos to stdunbar for steering me in the right direction.

When installing sharp on MacOS via NPM the normal way (i.e.: npm i sharp --save), the installer automatically adds binaries for OS X. But AWS lambda functions run on Linux 2 machines with x64 processors and this is why we get this error.

To fix you must first uninstall sharp completely and then run:

npm install --arch=x64 --platform=linux sharp

Note:

version 0.25 no longer works with the target flag. This used to work:

npm install --arch=x64 --platform=linux --target=10.15.0 sharp

Then deploy as usual from Serverless Framework with sls deploy

Side Note:

Sharp is EXTREMELY FAST!!! Before using sharp, I was using another image resizing utility named Jimp. It did the job, but was quite slow. To prevent timeout errors, I had to increase the memory size from 128 to 512 and the timeout from 5 seconds to 30 seconds just to handle a typical 1 megabyte image.

Here is a comparison between the two for resizing a 1.2Mb picture down to 600x400 using the same configuration:

Jimp -> used 512Mb of memory and AWS billed me for 14300 ms.

Sharp -> used 132 MB of memory and AWS billed me for 800 ms.

That's more than 14x faster than Jimp!!!

3
votes

I found an easier solution when building from MacOS or Windows, I use a Makefile with SAM and provide linux as a target for the NPM install.

template.yaml

  MyFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: mycode/
      Handler: handler.handler
      Runtime: nodejs12.x
      MemorySize: 512
      Timeout: 5
      Role: !GetAtt EdgeLambdaRole.Arn
    Metadata:
        BuildMethod: makefile

mycode/makefile

build-MyFunction:
    cp *.js $(ARTIFACTS_DIR)
    cp package.json $(ARTIFACTS_DIR)
    cp package-lock.json $(ARTIFACTS_DIR)
    cd $(ARTIFACTS_DIR) && npm install --production --arch=x64 --platform=linux

Make sure you use TABS in your makefile

2
votes

I was facing the same issue, when i do npm install --arch=x64 --platform=linux sharp in CMD in windows machine.

Fixed it by opening the CMD in Administrator mode, i did not find any error in running npm install --arch=x64 --platform=linux sharp

1
votes

If you like to yarn, set via environment variables

NOTE: I clean up the existing platform/arch first.

# For macOS/Windows, we can install natively
yarn remove sharp
yarn add sharp

# For AWS Lambda, we need to specify this when we package:
yarn remove sharp
npm_config_platform=linux npm_config_arch=x64 yarn add sharp
0
votes

If you use serverless along with serverless-webpack, you must use this custom-config in your serverless.yml file:

custom:
  # ...
  webpack:
    # ...
    packagerOptions:
      scripts:
        - npm install --arch=x64 --platform=linux sharp

0
votes

If you use SAM you could build your function inside an AWS Lambda-like Linux Docker container:

sam build -u