如何从使用Docker部署的AWS Lambda Python处理程序运行终端命令?

huangapple go评论78阅读模式
英文:

How to run terminal commands from AWS Lambda Python handler deployed using Docker?

问题

以下是 ChatGPT 建议的更改部分:

# 创建运行时目录
RUN mkdir -p /var/runtime

# 创建一个 shell 脚本来运行 Lambda 函数
RUN echo -e '#!/bin/sh\n/usr/local/bin/python -m awslambdaric $*' > /var/runtime/bootstrap
RUN chmod 755 /var/runtime/bootstrap

ENTRYPOINT ["/var/runtime/bootstrap"]
CMD ["app.handler"]

请尝试使用上述更改,然后构建和运行您的 Docker 容器。这些更改应该有助于解决 AWS Lambda 找不到正确入口点的问题。希望这能帮助您实现所需的功能。如果您仍然遇到问题,请提供更多详细信息以便进一步帮助。

英文:

I have an AWS Lambda docker image, where I install package named "praat" and want to call it from Python using subprocess. It fails probably due to the ENTRYPOINT, as when I changed it, I was able to run docker exec --workdir / aws-praat praat --help after creating a Docker container. But I couldn't figure out how to still have the AWS Lambda entry point.

The following is my Dockerfile

# Define function directory
ARG FUNCTION_DIR="/function"

FROM python:buster as build-image

# Install aws-lambda-cpp build dependencies
RUN apt-get update && \
    apt-get install -y \
    g++ \
    make \
    cmake \
    unzip \
    libcurl4-openssl-dev \
    praat

# Include global arg in this stage of the build
ARG FUNCTION_DIR
# Create function directory
RUN mkdir -p ${FUNCTION_DIR}

# Copy function code
COPY app/* ${FUNCTION_DIR}

# Install the runtime interface client
RUN pip install \
        --target ${FUNCTION_DIR} \
        awslambdaric

RUN pip install \
        --target ${FUNCTION_DIR} \
        boto3 

# Multi-stage build: grab a fresh copy of the base image
FROM arm64v8/python:buster

# Include global arg in this stage of the build
ARG FUNCTION_DIR

RUN apt-get update
RUN apt-get -y install praat

# Set working directory to function root directory
WORKDIR ${FUNCTION_DIR}

# Copy in the build image dependencies
COPY --from=build-image ${FUNCTION_DIR} ${FUNCTION_DIR}

ENTRYPOINT [ "/usr/local/bin/python", "-m", "awslambdaric" ]
CMD [ "app.handler" ]

The command I need to run is inside a function handler(event, context) in app/app.py file:

# Get file name without extension
file_name = os.path.splitext(s3_key)[0]

# Download the file from S3 to /tmp/
file_path = os.path.join(TEMPORARY_FOLDER, os.path.basename(s3_key))
s3.download_file(s3_bucket, s3_key, file_path)

# Copy the praat script, because it creates temporary files and otherwise may not run outside /tmp/
shutil.copy("analyse_csg_files_server.praat", os.path.join(TEMPORARY_FOLDER, "analyse_csg_files_server.praat"))

# Change the current working directory to /tmp/
os.chdir(TEMPORARY_FOLDER)

# Run the command
cmd = f'praat --run analyse_csg_files_server.praat \"{file_name}\"'
res = subprocess.call(cmd)  
print(res)

ChatGPT suggested following change:

# Create the runtime directory
RUN mkdir -p /var/runtime

# Create a shell script to run the Lambda function
RUN echo -e '#!/bin/sh\n/usr/local/bin/python -m awslambdaric $*' > /var/runtime/bootstrap
RUN chmod 755 /var/runtime/bootstrap

ENTRYPOINT [ "/var/runtime/bootstrap" ]
CMD [ "app.handler" ]

I played around with it a bit, but could not get it to start and was getting an error RequestId: 190c1fa1-f5a5-44de-b7ed-4075769eb307 Error: fork/exec /var/runtime/bootstrap: exec format error
Runtime.InvalidEntrypoint
at AWS.

How can I achieve this functionality?

答案1

得分: 1

参考文档可以在这里找到,如果您还没有看到它:
https://docs.aws.amazon.com/lambda/latest/dg/python-image.html

您可以尝试创建一个名为 entry.sh 的脚本,如下所示:

#!/bin/sh
if [ -z "${AWS_LAMBDA_RUNTIME_API}" ]; then
    exec /usr/bin/aws-lambda-rie /usr/local/bin/python -m awslambdaric $1
else
    exec /usr/local/bin/python -m awslambdaric $1
fi

Dockerfile 中,您可以这样做:

# (可选)添加 Lambda Runtime Interface Emulator 并在 ENTRYPOINT 中使用脚本以便在本地更简单地运行
ADD https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie /usr/bin/aws-lambda-rie
COPY entry.sh /
RUN chmod 755 /usr/bin/aws-lambda-rie /entry.sh

ENTRYPOINT [ "/entry.sh" ]
CMD [ "app.handler" ]

希望这能帮助您!

英文:

References to documentation can be found here if you haven't already seen it:
https://docs.aws.amazon.com/lambda/latest/dg/python-image.html

You can attempt to create an entry.sh script looks like this:

#!/bin/sh
if [ -z "${AWS_LAMBDA_RUNTIME_API}" ]; then
    exec /usr/bin/aws-lambda-rie /usr/local/bin/python -m awslambdaric $1
else
    exec /usr/local/bin/python -m awslambdaric $1
fi

Within the Dockerfile you could do this:

# (Optional) Add Lambda Runtime Interface Emulator and use a script in the ENTRYPOINT for simpler local runs
ADD https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie /usr/bin/aws-lambda-rie
COPY entry.sh /
RUN chmod 755 /usr/bin/aws-lambda-rie /entry.sh

ENTRYPOINT [ "/entry.sh" ]
CMD [ "app.handler" ]

Hope this helps!

huangapple
  • 本文由 发表于 2023年5月29日 18:11:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76356441.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定