无法使用 Linux Alpine docker 为 AWS lambda 构建 zip 文件
Can't build zip file for AWS lambda using Linux Alpine docker
我有基于 Alpine linux 的 Dockerfile,它为 AWS Lambda 构建 lambda.zip 文件。
这是 Dockerfile:
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 && \
runDeps="$(scanelf --needed --nobanner --recursive /usr/local \
| awk '{ gsub(/,/, "\nso:", ); print "so:" }' \
| xargs -r apk info --installed \
| sort -u)" && \
apk add --virtual .rundeps $runDeps
RUN geos-config --cflags
# -- Install python:
RUN apk add --update --no-cache python3-dev python3 \
&& python3 -m ensurepip --upgrade \
&& pip3 install --upgrade pip pipenv setuptools docker-compose awscli shapely wheel \
&& rm -r /usr/lib/python*/ensurepip \
&& if [ ! -e /usr/bin/pip ]; then ln -s pip3 /usr/bin/pip ; fi \
&& 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 中的那些包,我尝试测试 Shapely 包,例如 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
我在 Internet 上尝试了很多不同的解决方案,因此您可以在我的 Dockerfile 中看到一团糟,但它们都没有用。
您正在 Docker 环境中安装一些静态编译的依赖项,例如 libc-dev
、geos-dev
和 geos
。您还必须在 Lambda 部署 zip 文件中包含这些静态依赖项。此外,要包含在 AWS Lambda 中使用的静态编译依赖项,您必须使用 Lambda 使用的相同操作系统,即 Amazon Linux,而不是 Alpine Linux.
幸运的是,现在有两种选择可以让这一切变得更容易:
Lambda 层是 Lambda 依赖项,可以以可重用的方法打包,也可以与其他开发人员共享。在这种情况下 someone has already created a shapely Lambda Layer (and someone else here),您可以简单地将其包含在您的 Lambda 函数中,而不必尝试自行打包。
如果您仍想自己构建它,您可以查看该项目的源代码以了解他们是如何构建该层的。
您可以创建 Docker 映像并将其部署到 Lambda,而不是创建 zip 部署。如果你走这条路,你必须在你的 Lambda 容器中实现一个特定的接口,最简单的方法是从 official AWS Lambda base images.
之一开始
我有基于 Alpine linux 的 Dockerfile,它为 AWS Lambda 构建 lambda.zip 文件。 这是 Dockerfile:
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 && \
runDeps="$(scanelf --needed --nobanner --recursive /usr/local \
| awk '{ gsub(/,/, "\nso:", ); print "so:" }' \
| xargs -r apk info --installed \
| sort -u)" && \
apk add --virtual .rundeps $runDeps
RUN geos-config --cflags
# -- Install python:
RUN apk add --update --no-cache python3-dev python3 \
&& python3 -m ensurepip --upgrade \
&& pip3 install --upgrade pip pipenv setuptools docker-compose awscli shapely wheel \
&& rm -r /usr/lib/python*/ensurepip \
&& if [ ! -e /usr/bin/pip ]; then ln -s pip3 /usr/bin/pip ; fi \
&& 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 中的那些包,我尝试测试 Shapely 包,例如 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
我在 Internet 上尝试了很多不同的解决方案,因此您可以在我的 Dockerfile 中看到一团糟,但它们都没有用。
您正在 Docker 环境中安装一些静态编译的依赖项,例如 libc-dev
、geos-dev
和 geos
。您还必须在 Lambda 部署 zip 文件中包含这些静态依赖项。此外,要包含在 AWS Lambda 中使用的静态编译依赖项,您必须使用 Lambda 使用的相同操作系统,即 Amazon Linux,而不是 Alpine Linux.
幸运的是,现在有两种选择可以让这一切变得更容易:
Lambda 层是 Lambda 依赖项,可以以可重用的方法打包,也可以与其他开发人员共享。在这种情况下 someone has already created a shapely Lambda Layer (and someone else here),您可以简单地将其包含在您的 Lambda 函数中,而不必尝试自行打包。
如果您仍想自己构建它,您可以查看该项目的源代码以了解他们是如何构建该层的。
您可以创建 Docker 映像并将其部署到 Lambda,而不是创建 zip 部署。如果你走这条路,你必须在你的 Lambda 容器中实现一个特定的接口,最简单的方法是从 official AWS Lambda base images.
之一开始