I am writing a Lambda function to convert an excel file to PDF using unoconv with libreoffice, for this I am using alpine base image. The Dockerfile is as follows.
# Define global args
ARG FUNCTION_DIR="/home/app/"
ARG RUNTIME_VERSION="3.9"
ARG DISTRO_VERSION="3.12"
# Stage 1 - bundle base image + runtime
# Grab a fresh copy of the image and install GCC
FROM python:${RUNTIME_VERSION}-alpine${DISTRO_VERSION} AS python-alpine
# Install GCC (Alpine uses musl but we compile and link dependencies with GCC)
RUN apk add --no-cache \
libstdc++
# Stage 2 - build function and dependencies
FROM python-alpine AS build-image
# Install aws-lambda-cpp build dependencies
RUN apk add --no-cache \
build-base \
libtool \
autoconf \
automake \
libexecinfo-dev \
make \
cmake \
libcurl
# Include global args in this stage of the build
ARG FUNCTION_DIR
ARG RUNTIME_VERSION
# Create function directory
RUN mkdir -p ${FUNCTION_DIR}
# Copy handler function
COPY app.py ${FUNCTION_DIR}
COPY requirements.txt ${FUNCTION_DIR}
# Optional – Install the function's dependencies
RUN python${RUNTIME_VERSION} -m pip install -r /home/app/requirements.txt --target ${FUNCTION_DIR}
# Install Lambda Runtime Interface Client for Python
RUN python${RUNTIME_VERSION} -m pip install awslambdaric --target ${FUNCTION_DIR}
# Stage 3 - final runtime image
# Grab a fresh copy of the Python image
FROM python-alpine
# Include global arg in this stage of the build
ARG FUNCTION_DIR
# Set working directory to function root directory
WORKDIR ${FUNCTION_DIR}
# Copy in the built dependencies
COPY --from=build-image ${FUNCTION_DIR} ${FUNCTION_DIR}
#
ARG PUID=1000
ARG PGID=1000
#
RUN set -xe \
&& apk add --no-cache --purge -uU \
curl icu-libs unzip zlib-dev musl \
mesa-gl mesa-dri-swrast \
libreoffice libreoffice-base libreoffice-lang-uk \
ttf-freefont ttf-opensans ttf-ubuntu-font-family ttf-inconsolata \
ttf-liberation ttf-dejavu \
libstdc++ dbus-x11 \
&& echo "http://dl-cdn.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories \
&& echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \
&& echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \
&& apk add --no-cache -U \
ttf-font-awesome ttf-mononoki ttf-hack \
&& rm -rf /var/cache/apk/* /tmp/*
RUN pip install unoconv
# (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" ]
entry.sh file content is as follows.
#!/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
requirement.txt file content is as follows.
unotools
unoconv
boto3
the app.py file content is as follows.
import sys
import boto3
import subprocess
import json
def handler(event, context):
bucketname = "somebucket"
filename = "Sample/example.xlsx"
outputfilename = filename.rsplit('.', 1)[0] + '.pdf'
s3 = boto3.client('s3')
try:
s3.download_file(bucketname, filename, "file.xlsx")
except Exception as e:
return str(e)
try:
result = subprocess.run(['unoconv', '-f', 'pdf', "file.xlsx"], stdout=subprocess.PIPE)
except Exception as e:
return str(e)
try:
with open("file.pdf", "rb") as f:
s3.upload_fileobj(f, bucketname, outputfilename)
except Exception as e:
return str(e)
body = {
"message": "Converted excel to pdf"
}
response = {
"statusCode": 200,
"event": json.dumps(event),
"body": json.dumps(body),
"path": "app.py"
}
return response
I built this container and run the container locally and this works without problems. However, when I push the image to the ECR and update the function with new latest image, and run the test, it shows this error.
{
"errorMessage": "RequestId: SOME_ID_HERE Error: fork/exec /usr/local/bin/python awslambdaric: no such file or directory",
"errorType": "Runtime.InvalidEntrypoint"
}
IMAGE 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/]
Looking at the error I assume this is something related to the architecture. Can someone help me understand what is causing the issue ?