快速构建基于AWS Lambda容器镜像的OCR应用,aws lambda快速构建基于AWS Lambda容器镜像的OCR应用摘要AWS Lambda函数现已支持打包和部署容器镜像,开发者通过官方提供或自己构建镜像文件,可以非常方便利用现有的开发工具,工作流轻松构建基于AWS Lambda的应用程序。基于容器打包的应用......
摘要
AWS Lambda函数现已支持打包和部署容器镜像,开发者通过官方提供或自己构建镜像文件,可以非常方便利用现有的开发工具,工作流轻松构建基于AWS Lambda的应用程序。基于容器打包的应用通过AWS Lambda可以实现更为简便的操作部署,相比EC2有着更为快速的启动时间,更为强大的并发扩展以及高可用,同时无缝与140余种AWS服务集成。
本文将展示如何基于自建镜像(public.ecr.aws/bitnami/python:3.7),利用AWS官方提供的运行时接口客户端(RIC)和运行时接口仿真器(RIE),构建运行在AWS Lambda上的OCR应用。
前言
对于机器学习,图像处理等依赖库构建复杂且文件较大的应用,AWS Lambda支持最大10GB的容器镜像,开发者可以直接使用熟悉的容器开发工具(docker)在本地构建测试,并将容器镜像推国际快递Amazon ECR(全托管的容器注册表),之后通过指定Amazon ECR镜像来部署Lambda函数,免去了以往Lambda Layer构建流程,也无需受限于Lambda Layer的大小限制(250MB)。
伴随AWS Lambda对容器镜像支持的特性发布,AWS官方提供了一组Lambda基础镜像,可在Amazon ECR(gallery.ecr.aws/lambda)和Docker Hub(amazon/awslambdapython)上获取,该基础镜像预装了包括Node.js,Python,Java等语言的Lambda运行时,必要组件以及构建基础镜像的dockerfile。同时AWS官方还开源了运行时接口客户端(RIC)和运行时接口仿真器(RIE),方便用户构建同Lambda兼容的容器镜像并进行本地测试。
OCR应用我们基于tesseract(最早由HP Lab开发并于2005年开源)实现,其中软件依赖如pillow,libtesseract我们利用AWS进行本地安装,或者用户也可以选取官方镜像public.ecr.aws/lambda编译以尽可能保证同Lambda兼容。
流程概览
本文构建的OCR应用会利用到Python,Shell作为开发语言,PIP/Docker作为开发工具,构建流程分成如下部分:1)软件依赖库的构建,包括pillow,libtesseract编译;2)Lambda兼容镜像的构建,包括RIC/RIE的安装配置,Lambda业务代码的打包;3)Lambda业务代码实现,通过简单的代码调用生成的pytesseract库返回图片识别结果;4)本地调试验证,通过RIE实现本地功能调试和迭代。
其中构建容器镜像的软件依赖库有以下几个途径:方案一,直接利用已经包含软件依赖库的容器镜像,其dockerfile示例如下:
FROM public.ecr.aws/myrepo/sharedliblayer:1 AS sharedliblayer
#Layer code
WORKDIR/opt
COPYfrom=sharedliblayer/opt/.
方案二,利用已经构建好的Lambda Layer,通过curl的形式拉取到新的镜像当中,其dockerfile示例如下:
ARG AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION:cnnorthwest1}
ARG AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:}
ARG AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:}
ENV AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}
ENV AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
ENV AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
RUN apk add awscli curl unzip
RUN mkdirp/opt
RUN curl$(aws lambda getlayerversionbyarnarn arn:aws:lambda:useast1:1234567890123:layer:sharedliblayer:1queryContent.Locationoutput text)output layer.zip
RUN unzip layer.zipd/opt
RUN rm layer.zip
方案三,完全从零开始的用户可以考虑直接在容器里面构建软件依赖库,其dockerfile示例如下:
FROM python:3.8alpine AS installer
#Layer Code
COPY extensionssrc/opt/
COPY extensionssrc/requirements.txt/opt/
RUN pip installr/opt/requirements.txtt/opt/extensions/lib
FROM scratch AS base
WORKDIR/opt/extensions
COPYfrom=installer/opt/extensions.
接下来的OCR方案考虑到tesseract的依赖构建相对复杂,为了构建流程的独立和依赖库的共享,我们将采用方案二,即先利用Shell和Docker构建Lambda业务代码调用的所有依赖,再将构建完毕后的zip包存放到Lambda Layer中供后续Lambda镜像构建调用。
创建步骤
软件依赖库的构建
首先安装pillow,创建requirements文件,写入以下内容。
pillow
接着创建shell脚本(build_py37_pkgs.sh),写入以下内容并执行,执行完毕后会在相同目录下生成pythonlibslayer.zip文件。
sete
rmrf pythonlibslayer.zip exit 0
rmrf python/exit 0
docker runv$PWD:/var/tasklambci/lambda:buildpython3.7/bin/shcpip installr requirements.txtt python/lib/python3.7/sitepackages/;exit
chmod 777 python/
zipr pythonlibslayer.zip pythongt;/dev/null
rmrf python/
Pillow构建完毕后,开始构建tesseract依赖,创建dockerfile(Dockerfiletess4),文件内容可以直接参考这里
FROM lambci/lambdabase:build
#Proxy setup if exists
#ENV http_proxyhttp://ip:port
#ENV https_proxyhttps://ip:port
ARG LEPTONICA_VERSION=1.78.0
ARG TESSERACT_VERSION=4.1.0rc4
ARG AUTOCONF_ARCHIVE_VERSION=2017.09.28
ARG TMP_BUILD=/tmp
ARG TESSERACT=/opt/tesseract
ARG LEPTONICA=/opt/leptonica
ARG DIST=/opt/builddist
#change OCR_LANG to enable the layer for different languages
ARG OCR_LANG=chi_sim
#change TESSERACT_DATA_SUFFIX to use different datafiles(options:_best,_fastand)
ARG TESSERACT_DATA_SUFFIX=
ARG TESSERACT_DATA_VERSION=4.0.0
后续省略
……
创建shell脚本(build_tesseract4.sh),写入以下内容并执行,执行完毕后会在相同目录下生成tesseractlayer.zip
sete
rmrf tesseractlayer.zip exit 0
rmrf configs exit 0
rmrf tessconfigs exit 0
#Download tessconfigs folder
git clone https://github.com/tesseractocr/tessconfigs.git tesseractconfigs
mv tesseractconfigs/configs.
mv tesseractconfigs/tessconfigs.
rmrf tesseractconfigs
#Build Docker image containing Tesseract
docker buildt tess_layerf Dockerfiletess4.
#Copy Tesseract locally
CONTAINER=$(docker rund tess_layer false)
docker cp$CONTAINER:/opt/builddist layer
docker rm$CONTAINER
##Zip Tesseract
cd layer/
zipr../tesseractlayer.zip.
#Clean
cd..
rmrf layer/
rmrf tessconfigs/
rmrf configs/
将前面步骤生成的zip文件(pythonlibslayer.zip/tesseractlayer.zip)通过AWS Console或者AWS命令行的方式上传至Lambda Layer,并记录下对应的ARN,类似arn:awscn:lambda:cnnorthwest1:xxxxxxxx:layer:ocrTesseract:1。
Lambda兼容镜像的构建
运行时接口客户端(RIC)作为AWS开源项目,实现了Lambda的运行时API,包括调用事件检索,调用响应返回,调用错误处理和初始化错误等功能实现Lambda能正确接收处理调用并返回结果。运行时接口仿真器(RIE)实际是一个轻量级的web服务器,代理Lambda的运行时和扩展API,使开发者可以在本地通过Docker,CURL进行本地测试而不用将Lambda容器镜像部署上云。
接下来我们基于自建镜像(public.ecr.aws/bitnami/python:3.7)构建Lambda容器的dockerfile并针对其中部分操作进行解释。
创建entry.sh文件,用作容器在云上部署和本地调试的自动切换,内容如下:
if [ z ${AWS_LAMBDA_RUNTIME_API} ]; then
exec /usr/local/bin/awslambdarie /usr/local/bin/python m awslambdaric $1
else
exec /usr/local/bin/python m awslambdaric $1
fi
创建dockerfile(dockerfilecustomtesseract),内容摘录如下,原文件参见这里:
安装必要工具
ARG LAYER_DIR=/opt
FROM public.ecr.aws/bitnami/python:3.7 as buildimage
RUN aptget update \
aptget install y \
g++ \
make \
cmake \
unzip \
libcurl4openssldev
RUN pip install opencvpythonheadless
RUN aptget install y libpngdev
安装运行时接口客户端(RIC)
RUN mkdir p ${LAYER_DIR}
RUN pip install \
target ${LAYER_DIR} \
awslambdaric
取前面步骤生成的Lambda Layer
ARG AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION:cnnorthwest1}
ARG AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:xxxx}
ARG AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:xxxx}
ENV AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}
ENV AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
ENV AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
RUN aptget instally curl unzip
RUN curlhttps://awscli.amazonaws.com/awscliexelinuxx86_64.zipoawscliv2.zip
RUN unzip awscliv2.zip
RUN./aws/install
#ocrTesseract
RUN curl$(aws lambda getlayerversionbyarnarn arn:awscn:lambda:cnnorthwest1:xx:layer:ocrTesseract:3queryContent.Locationoutput text)output pythonlibslayer.zip
#COPY pythonlibslayer.zip.
RUN unzip pythonlibslayer.zipd${LAYER_DIR}
RUN rm pythonlibslayer.zip
#pythonlibslayer
RUN curl$(aws lambda getlayerversionbyarnarn arn:awscn:lambda:cnnorthwest1:xx:layer:pythonlibslayer:1queryContent.Locationoutput text)output tesseractlayer.zip
#COPY tesseractlayer.zip.
RUN unzip tesseractlayer.zipd${LAYER_DIR}
RUN rm tesseractlayer.zip
打包Lambda业务代码(代码逻辑下一小节会提到)和entry.sh
#Multistage build:grab a fresh copy of the base image,use custom image instead of official one
FROM public.ecr.aws/bitnami/python:3.7
#Include global arg in this stage of the build
ARG LAYER_DIR
#Copy in the build image dependencies
WORKDIR${LAYER_DIR}
COPYfrom=buildimage${LAYER_DIR}.
COPY app.py.
COPY entry.sh/
RUN chmod 755/entry.sh
ENV LD_LIBRARY_PATH=/opt:/opt/lib:${LD_LIBRARY_PATH}
ENV PATH=/opt:/opt/bin:${PATH}
#Production env
ENTRYPOINT[/entry.sh]
开始构建镜像并推国际快递ECR,至此OCR业务的Lambda镜像构建完毕
docker buildt locallambdapython3.8customocrbuildarg AWS_DEFAULT_REGION=cnnorthwest1buildarg AWS_ACCESS_KEY_ID=xxbuildarg AWS_SECRET_ACCESS_KEY=xxf dockerfilecustomtesseract.
docker tag locallambdapython3.8customocr:latest xx.dkr.ecr.cnnorthwest1.amazonaws.com.cn/locallambdapython3.8customocr
aws ecr getloginpasswordregion cnnorthwest1docker loginusername AWSpasswordstdin xx.dkr.ecr.cnnorthwest1.amazonaws.com.cn
docker push xx.dkr.ecr.cnnorthwest1.amazonaws.com.cn/locallambdapython3.8customocr:latest
Lambda业务代码实现
代码的调用逻辑如下,handler接收传入的图片文件(u64编码)并调用pytesseract实现图片中文字的识别并返回。
import sys
import os
sys.path.append(/opt/python/lib/python3.7/sitepackages)
# sys.path.append(/opt/python/lib/python3.7/sitepackages/pytesseract)
# sys.path.append(/opt/python/lib/python3.7/sitepackages/PIL)
# sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import base64
import pytesseract
import cv2
def write_to_file(save_path, data):
with open(save_path, wb) as f:
f.write(base64.b64decode(data))
def handler(event, context=None):
write_to_file(/tmp/photo.jpg, event[body])
img = cv2.imread(/tmp/photo.jpg)
ocr_text = pytesseract.image_to_string(img, config = eng)
# Return the result data in json format
return {
statusCode: 200,
body: ocr_text
}
本地调试验证
本地安装RIE,尽量减少Lambda镜像需要安装的文件
mkdirp~/.awslambdariecurlLo~/.awslambdarie/awslambdarie
https://github.com/aws/awslambdaruntimeinterfaceemulator/releases/latest/download/awslambdarie
chmod+x~/.awslambdarie/awslambdarie
本地运行容器并通过curl测试结果,其中helloWorld文件为显示有hello world字样图片对应的u64编码文件,成功的话我们可以看到输出的hello world。
docker rundv~/.awslambdarie:/awslambdap 9000:8080entrypoint/awslambda/awslambdarie locallambdapython3.8customocr:latest/usr/local/bin/pythonm awslambdaric app.handler
curlX POSThttp://localhost:9000/20150331/functions/function/invocationsd@helloWorld
待功能测试成功后我们可以将该镜像最终部署上云,无缝对接其他AWS服务实现更加丰富的功能。
对接其他服务
Lambda镜像构建完毕后,用户可以结合API Gateway实现HTTP前端调用来整合我们后端的OCR能力,通过SAM(Serverless Application Model)模版快速构建一个无服务器架构的OCR应用,示例模版部分内容如下所示:
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
PackageType: Image
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get
ImageUrl: ‘xxxx.dkr.ecr.cnnorthwest1.amazonaws.com.cn/locallambdapython3.8custom’
ImageConfig:
Command:
app.handler
EntryPoint:
/entry.sh
WorkingDirectory: /opt
Metadata:
DockerTag: python3.xv1
DockerContext: ./helloworld
Dockerfile: Dockerfile
之后通过SAM CLI实现AWS API Gateway,Lambda以及对应IAM的编译,调试和部署,有关SAM的具体的操作参见这里。待服务部署完毕后,用户可通过调用类似curl–request POSTH“ContentType:image/png”–databinary“@/path/ocrimage.png”https://xxxx.executeapi.cnnorthwest1.amazonaws.com.cn/prod/upload
命令获取OCR识别结果。
写在最后
Lambda针对容器镜像的支持,将无服务器化,容器这两个热门的技术领域进行了完美结合,用户在原有的容器开发环境基础上利用无服务器化架构的低运维,高扩展,高可用等特性,可以更加便捷的构建和开发诸如机器学习,图像识别等数据密集型负载应用。
特别声明:以上文章内容仅代表作者本人观点,不代表ESG跨境电商观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与ESG跨境电商联系。
二维码加载中...
使用微信扫一扫登录
使用账号密码登录
平台顾问
微信扫一扫
马上联系在线顾问
小程序
ESG跨境小程序
手机入驻更便捷
返回顶部