Не удается создать zip-файл для AWS lambda с помощью Linux Alpine docker

#python #docker #aws-lambda #alpine #shapely

Вопрос:

У меня есть докер-файл на основе Alpine linux, который строит lambda.zip файл для AWS Lambda. Вот Докерфайл:

 FROM alpine:3.12

# -- Install OS packages:
RUN apk add gcc
RUN apk add --update --no-cache 
    bash 
    build-base 
    cargo 
    curl 
    docker 
    # gcc 
    git 
    g   
    lftp 
    libc-dev 
    libffi-dev 
    libsodium-dev 
    libxslt-dev
    libzmq  
    zeromq-dev 
    make 
    musl-dev 
    ncftp 
    nodejs 
    npm 
    openssh-client 
    openssl 
    openssl-dev 
    rsync 
    su-exec 
    tar 
    wget 
    zip 
# geos  
# geos-dev 
# libc-dev 

WORKDIR /tmp/

RUN echo "http://mirror.leaseweb.com/alpine/edge/community" >> /etc/apk/repositories
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories
RUN apk add --virtual .build-deps 
    --repository http://dl-cdn.alpinelinux.org/alpine/edge/community 
    --repository http://dl-cdn.alpinelinux.org/alpine/edge/main 
    libc-dev geos-dev geos amp;amp; 
    runDeps="$(scanelf --needed --nobanner --recursive /usr/local 
    | awk '{ gsub(/,/, "nso:", $2); print "so:" $2 }' 
    | xargs -r apk info --installed 
    | sort -u)" amp;amp; 
    apk add --virtual .rundeps $runDeps

RUN geos-config --cflags

# -- Install python:
RUN apk add --update --no-cache python3-dev python3 
    amp;amp; python3 -m ensurepip --upgrade 
    amp;amp; pip3 install --upgrade pip pipenv setuptools docker-compose awscli shapely wheel 
    amp;amp; rm -r /usr/lib/python*/ensurepip  
    amp;amp; if [ ! -e /usr/bin/pip ]; then ln -s pip3 /usr/bin/pip ; fi 
    amp;amp; if [[ ! -e /usr/bin/python ]]; then ln
 

Вот скрипт, который работает с изображением docker Alpine и строит lambda.zip который содержит файлы python и все необходимые зависимости, такие как boto3, pip, six и т.д.

  
#!/bin/bash

set -x
set -e

pipenv install
rm -rf lambda.zip

VENV=$(pipenv --venv)
TEMPDIR=$(mktemp -d)

rsync -r --progress ./* ${TEMPDIR}
rsync -r --progress ${VENV}/lib/python3.8/site-packages/* ${TEMPDIR}

pushd ${TEMPDIR}
zip -r lambda.zip ./*
popd

cp ${TEMPDIR}/lambda.zip ./

cleanup() {
    rm -rf ${TEMPDIR}
}

trap cleanup EXIT
 

Затем я копирую это lambda.zip на мой локальный компьютер, распакуйте его и включите pipenv на моем локальном компьютере, чтобы использовать только эти пакеты в lambda.zip и я пытаюсь протестировать стройную упаковку, например test.py:

 from shapely.geometry import Polygon
print(Polygon([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]).minimum_clearance)
 

На AWS lambda и на моем локальном компьютере я получаю ту же ошибку с geos_c После:

 Traceback (most recent call last):
  File "test.py", line 1, in <module>
    from shapely.geometry import Polygon
  File "/home/stark/code/job/lamba_python_312_stack/shapely/geometry/__init__.py", line 4, in <module>
    from .base import CAP_STYLE, JOIN_STYLE
  File "/home/stark/code/job/lamba_python_312_stack/shapely/geometry/base.py", line 19, in <module>
    from shapely.coords import CoordinateSequence
  File "/home/stark/code/job/lamba_python_312_stack/shapely/coords.py", line 8, in <module>
    from shapely.geos import lgeos
  File "/home/stark/code/job/lamba_python_312_stack/shapely/geos.py", line 87, in <module>
    _lgeos = load_dll('geos_c', fallbacks=alt_paths)
  File "/home/stark/code/job/lamba_python_312_stack/shapely/geos.py", line 60, in load_dll
    raise OSError(
OSError: Could not find lib geos_c or load any of its variants ['libgeos_c.so.1', 'libgeos_c.so'].
 

Если я распакую файл, у меня получится что-то вроде этого:

 @user# ls

iohttp
aiohttp-3.7.4.post0.dist-info
attr
attrs-21.2.0.dist-info
boto3
boto3-1.18.38.dist-info
botocore
cron_runner.py
setuptools-58.0.4.virtualenv
shapely
Shapely-1.7.1.dist-info
...
xmltodict.py
yarl
yarl-1.6.3.dist-info

 

Я перепробовал множество различных решений в Интернете, так что вы можете увидеть беспорядок в моем файле Dockerfile, но они не сработали.

Ответ №1:

Вы устанавливаете некоторые статически скомпилированные зависимости в своей среде Docker, например libc-dev geos-dev , и geos . Вы также должны включить эти статические зависимости в zip-файл развертывания Lambda. Кроме того, чтобы включить статически скомпилированные зависимости для использования в AWS Lambda, вы должны использовать ту же операционную систему, которую использует Lambda, то есть Amazon Linux, а не Alpine Linux.


К счастью, сейчас есть две альтернативы, которые значительно облегчают это:

Лямбда-слои

Лямбда-слои-это лямбда-зависимости, которые могут быть упакованы в многоразовый метод, которым также можно поделиться с другими разработчиками. В этом случае кто-то уже создал красивый слой Лямбда (и кто-то еще здесь), который вы можете просто включить в свою функцию Лямбда, вместо того, чтобы пытаться упаковать его самостоятельно.

Если вы все еще хотите создать его самостоятельно, вы можете посмотреть исходный код этого проекта, чтобы узнать, как они создают слой.

Лямбда-контейнеры

Вместо создания развертывания zip вы можете создать образ Docker и развернуть его в Lambda. Если вы пойдете по этому пути, вам придется реализовать определенный интерфейс внутри вашего Лямбда-контейнера, и это проще всего сделать, начав с одного из официальных базовых образов AWS Lambda.