AWS Lambda Alpine Python 容器显示 IMAGE Launch 错误 exec 格式错误

Aje*_*shy 14 python docker aws-lambda unoconv alpine-linux

我正在编写一个 Lambda 函数,使用 unoconv 和 libreoffice 将 excel 文件转换为 PDF,为此我使用 alpine 基础图像。Dockerfile 如下。

\n
# Define global args\nARG FUNCTION_DIR="/home/app/"\nARG RUNTIME_VERSION="3.9"\nARG DISTRO_VERSION="3.12"\n\n# Stage 1 - bundle base image + runtime\n# Grab a fresh copy of the image and install GCC\nFROM python:${RUNTIME_VERSION}-alpine${DISTRO_VERSION} AS python-alpine\n# Install GCC (Alpine uses musl but we compile and link dependencies with GCC)\nRUN apk add --no-cache \\\n    libstdc++\n\n# Stage 2 - build function and dependencies\nFROM python-alpine AS build-image\n# Install aws-lambda-cpp build dependencies\nRUN apk add --no-cache \\\n    build-base \\\n    libtool \\\n    autoconf \\\n    automake \\\n    libexecinfo-dev \\\n    make \\\n    cmake \\\n    libcurl\n# Include global args in this stage of the build\nARG FUNCTION_DIR\nARG RUNTIME_VERSION\n# Create function directory\nRUN mkdir -p ${FUNCTION_DIR}\n# Copy handler function\nCOPY app.py ${FUNCTION_DIR}\nCOPY requirements.txt ${FUNCTION_DIR}\n# Optional \xe2\x80\x93 Install the function's dependencies\nRUN python${RUNTIME_VERSION} -m pip install -r /home/app/requirements.txt --target ${FUNCTION_DIR}\n# Install Lambda Runtime Interface Client for Python\nRUN python${RUNTIME_VERSION} -m pip install awslambdaric --target ${FUNCTION_DIR}\n\n# Stage 3 - final runtime image\n# Grab a fresh copy of the Python image\nFROM python-alpine\n# Include global arg in this stage of the build\nARG FUNCTION_DIR\n# Set working directory to function root directory\nWORKDIR ${FUNCTION_DIR}\n# Copy in the built dependencies\nCOPY --from=build-image ${FUNCTION_DIR} ${FUNCTION_DIR}\n\n#\nARG PUID=1000\nARG PGID=1000\n#\nRUN set -xe \\\n    && apk add --no-cache --purge -uU \\\n        curl icu-libs unzip zlib-dev musl \\\n        mesa-gl mesa-dri-swrast \\\n        libreoffice libreoffice-base libreoffice-lang-uk \\\n        ttf-freefont ttf-opensans ttf-ubuntu-font-family ttf-inconsolata \\\n    ttf-liberation ttf-dejavu \\\n        libstdc++ dbus-x11 \\\n    && echo "http://dl-cdn.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories \\\n    && echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \\\n    && echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \\\n    && apk add --no-cache -U \\\n    ttf-font-awesome ttf-mononoki ttf-hack \\\n    && rm -rf /var/cache/apk/* /tmp/*\n\nRUN pip install unoconv\n\n# (Optional) Add Lambda Runtime Interface Emulator and use a script in the ENTRYPOINT for simpler local runs\nADD https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie /usr/bin/aws-lambda-rie\nCOPY entry.sh /\nRUN chmod 755 /usr/bin/aws-lambda-rie /entry.sh\nENTRYPOINT [ "/entry.sh" ]\nCMD [ "app.handler" ]\n
Run Code Online (Sandbox Code Playgroud)\n

Entry.sh文件内容如下。

\n
#!/bin/sh\nif [ -z "${AWS_LAMBDA_RUNTIME_API}" ]; then\n    exec /usr/bin/aws-lambda-rie /usr/local/bin/python -m awslambdaric $1\nelse\n    exec /usr/local/bin/python -m awslambdaric $1\nfi\n
Run Code Online (Sandbox Code Playgroud)\n

requirement.txt文件内容如下。

\n
unotools\nunoconv\nboto3\n
Run Code Online (Sandbox Code Playgroud)\n

app.py文件内容如下。

\n
import sys\nimport boto3\nimport subprocess\nimport json\n\ndef handler(event, context):       \n    bucketname = "somebucket"\n    filename = "Sample/example.xlsx"\n    outputfilename = filename.rsplit('.', 1)[0] + '.pdf'\n\n    s3 = boto3.client('s3')\n\n    try:\n        s3.download_file(bucketname, filename, "file.xlsx")\n    except Exception as e:\n        return str(e)\n\n    try:\n        result = subprocess.run(['unoconv', '-f', 'pdf', "file.xlsx"], stdout=subprocess.PIPE)\n    except Exception as e:\n        return str(e)\n\n    try:\n        with open("file.pdf", "rb") as f:\n            s3.upload_fileobj(f, bucketname, outputfilename)\n    except Exception as e:\n        return str(e)\n\n    body = {\n        "message": "Converted excel to pdf"        \n    }\n    response = {\n        "statusCode": 200,\n        "event": json.dumps(event),\n        "body": json.dumps(body),\n        "path": "app.py"\n    }\n    return response\n
Run Code Online (Sandbox Code Playgroud)\n

我构建了这个容器并在本地运行该容器,这工作没有问题。但是,当我将映像推送到 ECR 并使用新的最新映像更新函数并运行测试时,它显示此错误。

\n
{\n  "errorMessage": "RequestId: SOME_ID_HERE Error: fork/exec /usr/local/bin/python awslambdaric: no such file or directory",\n  "errorType": "Runtime.InvalidEntrypoint"\n}\nIMAGE   Launch error: fork/exec /usr/local/bin/python awslambdaric: no such file or directory   Entrypoint: [/usr/local/bin/python awslambdaric]    Cmd: [app.handler]  WorkingDir: [/home/app/]\n
Run Code Online (Sandbox Code Playgroud)\n

查看错误,我认为这与架构有关。有人可以帮助我了解导致问题的原因吗?

\n

Aje*_*shy 54

问题在于架构,我正在 Mac Mini M1 上构建我的映像。当我通过提供 --platform=linux/amd64 选项构建映像时,错误消失了。当然,Lambda 函数中唯一可写的文件夹是 /tmp,因此,我也必须更改它才能正常工作。

  • 不得不浪费我生命中的两个小时才得到这个答案......谢谢! (6认同)

小智 23

我在 M1 Pro 上遇到了同样的问题,必须使用docker buildx进行构建来解决问题。

docker buildx build --platform linux/amd64 -f ./Dockerfile -t myDockerTag .
Run Code Online (Sandbox Code Playgroud)

  • 泰救了我一些精神创伤...... (2认同)

小智 6

对于访问此的任何人来说,问题也可能是由于该映像是在与 AWS 指定的不同的 CPU 架构上构建的。例如,如果您在 M1 上构建了映像,则必须在 lambda 映像对话框中选择arm64选项。