16

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?

Keith Harris
  • 1,118
  • 3
  • 13
  • 25
  • You need to build in a Linux environment as it is different from a Mac O/S environment. – stdunbar Feb 12 '20 at 17:02
  • I believe you're right. But how do I do that? And why is sharp environment dependent? – Keith Harris Feb 12 '20 at 18:38
  • 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 Feb 12 '20 at 19:00

8 Answers8

30

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!!!

Keith Harris
  • 1,118
  • 3
  • 13
  • 25
  • 1
    I tried this `npm install --arch=x64 --platform=linux sharp -save` and deployed with serverless, still get this error. I am on mac. – roy Jun 19 '20 at 23:05
  • It's not -save, it's --save. And you don't need it. Remember to completely uninstall sharp before running the above command. – Keith Harris Jun 22 '20 at 05:23
  • I couldn't get this to build and deploy to CloudFoundry via mac properly. But, you've got me on the right track. I used a linux VM to build, and that worked. Thanks!!! – Sean Novak Jul 18 '21 at 11:20
  • 1
    this works thank you! Do you know if there's a way to install both the mac AND linux version so that I can test locally too? – Chris Jones Oct 09 '21 at 17:59
6

If you are using Docker like I am and come across this issue.

Most likely your node_modules folder is being copied from your host machine into the docker container.

Why? Because your node_modules folder downloads modules specific to the architecture of your machine (in my case Mac), when you take these packages and try to run them in the container OS, it causes issues because the binaries are for mac (darwin-x64) and it tries to run them on linux (linux-x64) inside the container

To fix it, create a file named .dockerignore in the same directory as your Dockerfile and update it accordingly.

.dockerignore

node_modules/

Dockerfile

FROM node:latest
WORKDIR /usr/src/app
COPY package*.json ./
RUN ["npm", "install"]
COPY . .
CMD ["npm", "start"]

It will now ignore the node_modules folder on the host machine, and re-populate the modules once command npm install inside the Dockerfile has run.

Munib
  • 957
  • 1
  • 14
  • 30
4

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

maxime
  • 1,993
  • 3
  • 28
  • 57
3

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
sonjz
  • 4,870
  • 3
  • 42
  • 60
2

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

Ravikumar K
  • 85
  • 2
  • 11
  • This fixed my issue where I was getting the error below when I ran 'amplify push': npm ERR! path ...\amplify\backend\function\AmplifyFunction\src\node_modules\.bin\semver.cmd npm ERR! code EEXIST npm ERR! File exists: ...\amplify\backend\function\AmplifyFunction\src\node_modules\.bin\semver.cmd npm ERR! Move it away, and try again. – Duzmac Mar 31 '21 at 23:32
1

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

jrobichaud
  • 1,272
  • 1
  • 11
  • 23
0

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

sam build -u
Alex Rewa
  • 319
  • 4
  • 11
0

For anyone stumbling upon this post now. I've accomplished this by copying my package.json file into an AWS Cloud9 IDE and simply running npm install. From there, just download the node_modules/ folder.