AWS Lambda使用Node.js本地模块

3

最近我开始使用AWS Lambda函数,我的Nodejs应用程序一直运行良好,直到我尝试使用web3.js软件包。在我添加了这行代码后

const Web3 = require('web3');

我在 HTTP 终端点上遇到了 "Internal Server Error" 错误,并在 CloudWatch 日志中看到了以下内容

module initialization error: Error
at Object.Module._extensions..node (module.js:681:18)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Module.require (module.js:596:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (/var/task/node_modules/scrypt/index.js:3:20)
at Module._compile (module.js:652:30)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)

在本地我使用web3.js包没有问题。所以我开始深入了解这里出了什么问题。依赖中有一些本地模块。通过一些搜索,得出的想法是这些包应该在Amazon Linux平台上进行编译,否则它将无法工作。我开始创建docker镜像以达到这个目标。

Dockerfile

FROM amazonlinux:latest

# Install development tools
RUN yum update -y \
  && yum install gcc gcc44 gcc-c++ libgcc44 make cmake tar gzip git -y

# Install nvm and nodejs
RUN touch ~/.bashrc \
  && curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash \
  && source ~/.bashrc \
  && nvm install v8.10

CMD source ~/.bashrc && npm install

现在我在应用程序的根目录中运行以下命令,使用带有Amazon Linux的docker镜像安装npm包并编译本机模块。
docker run -it --rm -v $(pwd):/app -w /app docker/awslinuximage

我使用serverless框架进行部署。理论上,Lambda函数应该在部署后工作,但实际上并不是这样。我在Stackoverflow上找到了类似的问题,但没有什么帮助。
此外,我认为云函数支持Nodejs原生模块是一个普遍的问题,需要为特定的操作系统编译。
如果您有任何想法和帮助来解决这个问题,将不胜感激。谢谢。

可能是重复的问题:如何在AWS Lambda中加载模块? - stdunbar
不,我的问题不是部署。我使用无服务器进行部署,并且它运行良好。问题似乎是lambda在使用nodejs本地模块时存在一些问题,即使我使用亚马逊Linux Docker镜像进行编译。或者我可能遗漏了一些重要的东西。 - Rashad Ibrahimov
我不熟悉使用Docker镜像的过程,但是有一个官方AMI,可以创建兼容的构建环境。 - Michael - sqlbot
我使用了amazonlinux的docker镜像,也许值得尝试lambda镜像https://hub.docker.com/r/lambci/lambda/。谢谢你提供的链接和想法,我会去查看的。 - Rashad Ibrahimov
2个回答

1
web3使用的scrypt二进制文件必须在Lambda的执行环境上编译,该环境在docs中指定,才能使函数正常工作。详细说明可以在this博客文章的末尾找到。您可以使用以下Dockerfile自动化此过程,而无需创建实例。
FROM amazonlinux:2017.03.1.20170812

SHELL ["/bin/bash", "-c"] 

RUN yum update -y && \
    yum groupinstall -y "Development Tools"

# Install node using nvm 
ENV NVM_VERSION v0.33.11
ENV NVM_DIR /root/.nvm
RUN mkdir -p ${NVM_DIR}
RUN touch ~/.bashrc && chmod +x ~/.bashrc

RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash

ENV NODE_VERSION v8.10.0
RUN source ${NVM_DIR}/nvm.sh && \
    nvm install ${NODE_VERSION} && \
    nvm alias default ${NODE_VERSION} && \
    nvm use default

ENV NODE_PATH ${NVM_DIR}/${NODE_VERSION}/lib/node_modules
ENV PATH ${NVM_DIR}/versions/node/${NODE_VERSION}/bin:${PATH}

# Install global dependencies
RUN npm install -g node-gyp && \
    npm i -g serverless@1.39.1

# Set aws credentials in the image for serverless to use
# Save your aws (credentials/config) files at ./secrets.aws.(credentials/config) 
COPY ./secrets.aws.credentials /root/.aws/credentials
COPY ./secrets.aws.config /root/.aws/config

ENV APP_PATH /usr/src/app
WORKDIR ${APP_PATH}

# Install app dependencies
COPY package*.json ./
RUN npm install

COPY . .

CMD [ "sls", "deploy" ]

构建并运行Dockerfile

docker run --rm -it $(docker build -q .)

希望能帮到你。

0

我不想简单地回答一个链接,但你可以在构建.node文件方面找到一些信息。这通常被称为node-addon-api。它允许您编译"本机扩展"(以.node结尾的文件)。是的,您需要针对目标平台和node版本进行编译。然而,您不需要在每次部署/生成时启动Docker镜像。您只需复制沿途的 .node 文件即可。您甚至可以在本地运行Docker并执行此操作。这应该大大简化您的流程。

我使用AWS Lambda和Node.js 8.10中的另一个专有驱动程序模块来使用它,它完全正常运行。因此,我可以确认这些本机模块确实可以在AWS Lambda中工作。实际上,据我所知,编译它的公司针对的是"linux",而不是某个特定的AWS Lambda Linux变体。因此,当您需要编译东西时,这似乎是更宽容的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接