快速構(gòu)建基于AWS Lambda容器鏡像的OCR應(yīng)用,aws lambda快速構(gòu)建基于AWS Lambda容器鏡像的OCR應(yīng)用摘要AWS Lambda函數(shù)現(xiàn)已支持打包和部署容器鏡像,開(kāi)發(fā)者通過(guò)官方提供或自己構(gòu)建鏡像文件,可以非常方便利用現(xiàn)有的開(kāi)發(fā)工具,工作流輕松構(gòu)建基于AWS Lambda的應(yīng)用程序?;谌萜鞔虬膽?yīng)用......
摘要
AWS Lambda函數(shù)現(xiàn)已支持打包和部署容器鏡像,開(kāi)發(fā)者通過(guò)官方提供或自己構(gòu)建鏡像文件,可以非常方便利用現(xiàn)有的開(kāi)發(fā)工具,工作流輕松構(gòu)建基于AWS Lambda的應(yīng)用程序?;谌萜鞔虬膽?yīng)用通過(guò)AWS Lambda可以實(shí)現(xiàn)更為簡(jiǎn)便的操作部署,相比EC2有著更為快速的啟動(dòng)時(shí)間,更為強(qiáng)大的并發(fā)擴(kuò)展以及高可用,同時(shí)無(wú)縫與140余種AWS服務(wù)集成。
本文將展示如何基于自建鏡像(public.ecr.aws/bitnami/python:3.7),利用AWS官方提供的運(yùn)行時(shí)接口客戶端(RIC)和運(yùn)行時(shí)接口仿真器(RIE),構(gòu)建運(yùn)行在AWS Lambda上的OCR應(yīng)用。
前言
對(duì)于機(jī)器學(xué)習(xí),圖像處理等依賴庫(kù)構(gòu)建復(fù)雜且文件較大的應(yīng)用,AWS Lambda支持最大10GB的容器鏡像,開(kāi)發(fā)者可以直接使用熟悉的容器開(kāi)發(fā)工具(docker)在本地構(gòu)建測(cè)試,并將容器鏡像推國(guó)際快遞Amazon ECR(全托管的容器注冊(cè)表),之后通過(guò)指定Amazon ECR鏡像來(lái)部署Lambda函數(shù),免去了以往Lambda Layer構(gòu)建流程,也無(wú)需受限于Lambda Layer的大小限制(250MB)。
伴隨AWS Lambda對(duì)容器鏡像支持的特性發(fā)布,AWS官方提供了一組Lambda基礎(chǔ)鏡像,可在Amazon ECR(gallery.ecr.aws/lambda)和Docker Hub(amazon/awslambdapython)上獲取,該基礎(chǔ)鏡像預(yù)裝了包括Node.js,Python,Java等語(yǔ)言的Lambda運(yùn)行時(shí),必要組件以及構(gòu)建基礎(chǔ)鏡像的dockerfile。同時(shí)AWS官方還開(kāi)源了運(yùn)行時(shí)接口客戶端(RIC)和運(yùn)行時(shí)接口仿真器(RIE),方便用戶構(gòu)建同Lambda兼容的容器鏡像并進(jìn)行本地測(cè)試。
OCR應(yīng)用我們基于tesseract(最早由HP Lab開(kāi)發(fā)并于2005年開(kāi)源)實(shí)現(xiàn),其中軟件依賴如pillow,libtesseract我們利用AWS進(jìn)行本地安裝,或者用戶也可以選取官方鏡像public.ecr.aws/lambda編譯以盡可能保證同Lambda兼容。
流程概覽
本文構(gòu)建的OCR應(yīng)用會(huì)利用到Python,Shell作為開(kāi)發(fā)語(yǔ)言,PIP/Docker作為開(kāi)發(fā)工具,構(gòu)建流程分成如下部分:1)軟件依賴庫(kù)的構(gòu)建,包括pillow,libtesseract編譯;2)Lambda兼容鏡像的構(gòu)建,包括RIC/RIE的安裝配置,Lambda業(yè)務(wù)代碼的打包;3)Lambda業(yè)務(wù)代碼實(shí)現(xiàn),通過(guò)簡(jiǎn)單的代碼調(diào)用生成的pytesseract庫(kù)返回圖片識(shí)別結(jié)果;4)本地調(diào)試驗(yàn)證,通過(guò)RIE實(shí)現(xiàn)本地功能調(diào)試和迭代。
其中構(gòu)建容器鏡像的軟件依賴庫(kù)有以下幾個(gè)途徑:方案一,直接利用已經(jīng)包含軟件依賴庫(kù)的容器鏡像,其dockerfile示例如下:
FROM public.ecr.aws/myrepo/sharedliblayer:1 AS sharedliblayer
#Layer code
WORKDIR/opt
COPYfrom=sharedliblayer/opt/.
方案二,利用已經(jīng)構(gòu)建好的Lambda Layer,通過(guò)curl的形式拉取到新的鏡像當(dāng)中,其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
方案三,完全從零開(kāi)始的用戶可以考慮直接在容器里面構(gòu)建軟件依賴庫(kù),其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.
接下來(lái)的OCR方案考慮到tesseract的依賴構(gòu)建相對(duì)復(fù)雜,為了構(gòu)建流程的獨(dú)立和依賴庫(kù)的共享,我們將采用方案二,即先利用Shell和Docker構(gòu)建Lambda業(yè)務(wù)代碼調(diào)用的所有依賴,再將構(gòu)建完畢后的zip包存放到Lambda Layer中供后續(xù)Lambda鏡像構(gòu)建調(diào)用。
創(chuàng)建步驟
軟件依賴庫(kù)的構(gòu)建
首先安裝pillow,創(chuàng)建requirements文件,寫(xiě)入以下內(nèi)容。
pillow
接著創(chuàng)建shell腳本(build_py37_pkgs.sh),寫(xiě)入以下內(nèi)容并執(zhí)行,執(zhí)行完畢后會(huì)在相同目錄下生成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構(gòu)建完畢后,開(kāi)始構(gòu)建tesseract依賴,創(chuàng)建dockerfile(Dockerfiletess4),文件內(nèi)容可以直接參考這里
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
后續(xù)省略
……
創(chuàng)建shell腳本(build_tesseract4.sh),寫(xiě)入以下內(nèi)容并執(zhí)行,執(zhí)行完畢后會(huì)在相同目錄下生成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)通過(guò)AWS Console或者AWS命令行的方式上傳至Lambda Layer,并記錄下對(duì)應(yīng)的ARN,類似arn:awscn:lambda:cnnorthwest1:xxxxxxxx:layer:ocrTesseract:1。
Lambda兼容鏡像的構(gòu)建
運(yùn)行時(shí)接口客戶端(RIC)作為AWS開(kāi)源項(xiàng)目,實(shí)現(xiàn)了Lambda的運(yùn)行時(shí)API,包括調(diào)用事件檢索,調(diào)用響應(yīng)返回,調(diào)用錯(cuò)誤處理和初始化錯(cuò)誤等功能實(shí)現(xiàn)Lambda能正確接收處理調(diào)用并返回結(jié)果。運(yùn)行時(shí)接口仿真器(RIE)實(shí)際是一個(gè)輕量級(jí)的web服務(wù)器,代理Lambda的運(yùn)行時(shí)和擴(kuò)展API,使開(kāi)發(fā)者可以在本地通過(guò)Docker,CURL進(jìn)行本地測(cè)試而不用將Lambda容器鏡像部署上云。
接下來(lái)我們基于自建鏡像(public.ecr.aws/bitnami/python:3.7)構(gòu)建Lambda容器的dockerfile并針對(duì)其中部分操作進(jìn)行解釋。
創(chuàng)建entry.sh文件,用作容器在云上部署和本地調(diào)試的自動(dòng)切換,內(nèi)容如下:
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
創(chuàng)建dockerfile(dockerfilecustomtesseract),內(nèi)容摘錄如下,原文件參見(jiàn)這里:
安裝必要工具
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
安裝運(yùn)行時(shí)接口客戶端(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業(yè)務(wù)代碼(代碼邏輯下一小節(jié)會(huì)提到)和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]
開(kāi)始構(gòu)建鏡像并推國(guó)際快遞ECR,至此OCR業(yè)務(wù)的Lambda鏡像構(gòu)建完畢
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業(yè)務(wù)代碼實(shí)現(xiàn)
代碼的調(diào)用邏輯如下,handler接收傳入的圖片文件(u64編碼)并調(diào)用pytesseract實(shí)現(xiàn)圖片中文字的識(shí)別并返回。
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
}
本地調(diào)試驗(yàn)證
本地安裝RIE,盡量減少Lambda鏡像需要安裝的文件
mkdirp~/.awslambdariecurlLo~/.awslambdarie/awslambdarie
https://github.com/aws/awslambdaruntimeinterfaceemulator/releases/latest/download/awslambdarie
chmod+x~/.awslambdarie/awslambdarie
本地運(yùn)行容器并通過(guò)curl測(cè)試結(jié)果,其中helloWorld文件為顯示有hello world字樣圖片對(duì)應(yīng)的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
待功能測(cè)試成功后我們可以將該鏡像最終部署上云,無(wú)縫對(duì)接其他AWS服務(wù)實(shí)現(xiàn)更加豐富的功能。
對(duì)接其他服務(wù)
Lambda鏡像構(gòu)建完畢后,用戶可以結(jié)合API Gateway實(shí)現(xiàn)HTTP前端調(diào)用來(lái)整合我們后端的OCR能力,通過(guò)SAM(Serverless Application Model)模版快速構(gòu)建一個(gè)無(wú)服務(wù)器架構(gòu)的OCR應(yīng)用,示例模版部分內(nèi)容如下所示:
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
之后通過(guò)SAM CLI實(shí)現(xiàn)AWS API Gateway,Lambda以及對(duì)應(yīng)IAM的編譯,調(diào)試和部署,有關(guān)SAM的具體的操作參見(jiàn)這里。待服務(wù)部署完畢后,用戶可通過(guò)調(diào)用類似curl–request POSTH“ContentType:image/png”–databinary“@/path/ocrimage.png”https://xxxx.executeapi.cnnorthwest1.amazonaws.com.cn/prod/upload
命令獲取OCR識(shí)別結(jié)果。
寫(xiě)在最后
Lambda針對(duì)容器鏡像的支持,將無(wú)服務(wù)器化,容器這兩個(gè)熱門(mén)的技術(shù)領(lǐng)域進(jìn)行了完美結(jié)合,用戶在原有的容器開(kāi)發(fā)環(huán)境基礎(chǔ)上利用無(wú)服務(wù)器化架構(gòu)的低運(yùn)維,高擴(kuò)展,高可用等特性,可以更加便捷的構(gòu)建和開(kāi)發(fā)諸如機(jī)器學(xué)習(xí),圖像識(shí)別等數(shù)據(jù)密集型負(fù)載應(yīng)用。
特別聲明:以上文章內(nèi)容僅代表作者本人觀點(diǎn),不代表ESG跨境電商觀點(diǎn)或立場(chǎng)。如有關(guān)于作品內(nèi)容、版權(quán)或其它問(wèn)題請(qǐng)于作品發(fā)表后的30日內(nèi)與ESG跨境電商聯(lián)系。
二維碼加載中...
使用微信掃一掃登錄
使用賬號(hào)密碼登錄
平臺(tái)顧問(wèn)
微信掃一掃
馬上聯(lián)系在線顧問(wèn)
小程序
ESG跨境小程序
手機(jī)入駐更便捷
返回頂部