亚马逊AWS官方博客
快速构建基于 Lambda 容器镜像的 OCR 应用
摘要
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/aws-lambda-python)上获取,该基础镜像预装了包括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示例如下:
方案二,利用已经构建好的Lambda Layer,通过curl的形式拉取到新的镜像当中,其dockerfile示例如下:
方案三,完全从零开始的用户可以考虑直接在容器里面构建软件依赖库,其dockerfile示例如下:
接下来的OCR方案考虑到tesseract的依赖构建相对复杂,为了构建流程的独立和依赖库的共享,我们将采用方案二,即先利用Shell和Docker构建Lambda业务代码调用的所有依赖,再将构建完毕后的zip包存放到Lambda Layer中供后续Lambda镜像构建调用。
创建步骤
软件依赖库的构建
首先安装pillow,创建requirements文件,写入以下内容。
pillow
接着创建shell脚本(build_py37_pkgs.sh),写入以下内容并执行,执行完毕后会在相同目录下生成pythonlibs-layer.zip文件。
Pillow构建完毕后,开始构建tesseract依赖,创建dockerfile(Dockerfile-tess4),文件内容可以直接参考这里
创建shell脚本(build_tesseract4.sh),写入以下内容并执行,执行完毕后会在相同目录下生成tesseract-layer.zip
将前面步骤生成的zip文件(pythonlibs-layer.zip/tesseract-layer.zip)通过AWS Console或者AWS命令行的方式上传至Lambda Layer,并记录下对应的ARN,类似arn:aws-cn:lambda:cn-northwest-1: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文件,用作容器在云上部署和本地调试的自动切换,内容如下:
创建dockerfile(dockerfile-custom-tesseract),内容摘录如下,原文件参见这里:
安装必要工具
安装运行时接口客户端(RIC)
取前面步骤生成的Lambda Layer
打包Lambda业务代码(代码逻辑下一小节会提到)和entry.sh
开始构建镜像并推送到ECR,至此OCR业务的Lambda镜像构建完毕
Lambda业务代码实现
代码的调用逻辑如下,handler接收传入的图片文件(u64编码)并调用pytesseract实现图片中文字的识别并返回。
本地调试验证
本地安装RIE,尽量减少Lambda镜像需要安装的文件
本地运行容器并通过curl测试结果,其中helloWorld文件为显示有hello world字样图片对应的u64编码文件,成功的话我们可以看到输出的hello world。
待功能测试成功后我们可以将该镜像最终部署上云,无缝对接其他AWS服务实现更加丰富的功能。
对接其他服务
Lambda镜像构建完毕后,用户可以结合API Gateway实现HTTP前端调用来整合我们后端的OCR能力,通过SAM(Serverless Application Model)模版快速构建一个无服务器架构的OCR应用,示例模版部分内容如下所示:
之后通过SAM CLI实现AWS API Gateway,Lambda以及对应IAM的编译,调试和部署,有关SAM的具体的操作参见这里。待服务部署完毕后,用户可通过调用类似curl –request POST -H “Content-Type: image/png” –data-binary “@/path/ocrimage.png” https://xxxx.execute-api.cn-northwest-1.amazonaws.com.cn/prod/upload
命令获取OCR识别结果。
写在最后
Lambda针对容器镜像的支持,将无服务器化,容器这两个热门的技术领域进行了完美结合,用户在原有的容器开发环境基础上利用无服务器化架构的低运维,高扩展,高可用等特性,可以更加便捷的构建和开发诸如机器学习,图像识别等数据密集型负载应用。