【AWS Lambda】独自のコンテナイメージを超シンプルに使用する方法


概要

AWS LambdaでContainer Image Supportが発表されました。
AWS Lambda の新機能 – コンテナイメージのサポート

しかし、『AWSに用意してあるコンテナイメージではなく、独自コンテナを使いたい』時の方法が、
AWS公式ドキュメントだと癖があって少しわかりづらい内容です。

なので、独自コンテナイメージを使用したlambdaシンプルにデプロイ・実行する方法
について書いていきます。

対象読者

  • Dockerやコンテナの知識がある。
  • AWSのLambdaのざっくりとした知識がある。
  • aws-cliをインストール・セットアップしている。

重要なポイント

以下のポイントさえ押さえればOKです!

1. 2つのライブラリを'Dockerfile内'でインストールする。
    - 'awslambdaric'
    - 'runtime interface emulator'
2. 上記2つ用いたスクリプト'entry.sh'を、Dokcerのentrypointにする。

詳しくはこの後の記事を呼んでください。

ハンズオン

以下の流れで行います。
1. ファイルの準備
2. Image作成・ローカルでの実行
3. Imageのデプロイ
4. Lambdaの設定・実行

今回のディレクトリ構成です。
応用したいときは、Dockerfileapp.pyを改造してください。

# ディレクトリ構成
├── Dockerfile # 依存ライブラリのインストールをする。
├── entry.sh #  entrypointに指定するファイル
└── app
    └── app.py # 実行したいpythonスクリプト。

(1) ファイルの準備

Dockerfile

Dockerfile

# 今回は、buster(LinuxディストリビューションのOS)を使用。
FROM python:3.9-buster

# runtime interface consoleのインストール
RUN pip install awslambdaric

# localで実行するために、runtime interface emulatorのinstall
ADD https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie /usr/bin/aws-lambda-rie
RUN chmod 755 /usr/bin/aws-lambda-rie
COPY entry.sh "/entry.sh"
RUN chmod 755 /entry.sh

# 実行ファイルをコンテナ内に配置。
ARG APP_DIR="/home/app/"
WORKDIR ${APP_DIR}
COPY app ${APP_DIR}

ENTRYPOINT [ "/bin/bash", "/entry.sh" ]
CMD [ "app.handler" ]

entry.sh

ローカルであるか、AWS Lambda上のコンテナであるかを判断して、
aws-lambda-rieawslambdaricを使用します。
公式そのままのスクリプトです。

app/entry.sh
# localの場合
if [ -z "${AWS_LAMBDA_RUNTIME_API}" ]; then
    exec /usr/bin/aws-lambda-rie /usr/local/bin/python -m awslambdaric $1
# AWS Lambda上の場合
else
    exec /usr/local/bin/python -m awslambdaric $1
fi

注意1
/usr/local/bin/pythonとか/entry.shにしてるのは、lambdaの仕様で、コマンドは絶対バスで書く必要あるらしいです。
絶対パスでない場合、ローカルでは動きますが、Lambdaで実行すると以下のようなエラーが生じます。
IMAGE Launch error: Couldn't find valid bootstrap(s): [python] Entrypoint: []

 

注意2
pythonのpathである、/usr/local/bin/pythonは、
使用するDockerImageやpythonのインストールの方法で変わります。
Container内でwhich pythonをすることで、
pythonまでの絶対パスを調べてください。

app/app.py

実行したいソースコードです。

app/app.py
def handler(event, context):
    return "Hello world!!"

(2) イメージの作成・ローカルでの実行

まずはイメージを作成します。

# イメージの作成
docker build -t container_lambda .

# localでコンテナを立ち上げる
docker run -it --rm -p 9000:8080 container_lambda
> NFO[0000] exec '/usr/local/bin/python' (cwd=/home/app, handler=app.handler) 

# localのコンテナにリクエストを投げる
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
> "Hello world!!"% 

するとHello World!!が返ってきました!
ローカルでの実行成功です。
実行するファイルや関数を変えたいときは、CMDで指定するhandlerを変更しましょう。

(3) イメージのデプロイ

実際にLambdaで動かすために、AWSのElastic Container Registory(ECR)にイメージを登録します。
まずは、ECRの画面にうつりましょう。

リポジトリ作成を押します。

今回は、container_lambdaという名前でリポジトリを作成します。

名前を決めたら、一番下のリポジトリ作成を押してください

次に、このリポジトリにlocalのimageのpushします。

# imageの名前を指定。
IMAGENAME=container_lambda

# ECRのURLを指定。
REGISTRYURL=xxxxxxxxx.ecr.ap-northeast-1.amazonaws.com

# AWS ECR にログイン。
aws ecr get-login-password | docker login --username AWS --password-stdin $REGISTRYURL

# imageの作成、およびAWS ECRへのデプロイ。
docker build -t ${IMAGENAME} .
docker tag ${IMAGENAME} 386617633989.dkr.ecr.ap-northeast-1.amazonaws.com/${IMAGENAME}
docker push 386617633989.dkr.ecr.ap-northeast-1.amazonaws.com/${IMAGENAME}

これでimageをデプロイすることができました。

(4) Lambdaの設定・実行

最後にLambdaで実行しましょう!
まずはAWSコンソールから、Lambdaの画面に行き、関数の作成を押します。

  1. コンテナイメージを選択
  2. 関数名をつける(今回はcontainer_lambda)
  3. 先ほどデプロイしたDocker Imageを指定 そして関数の作成を押すと、画面が遷移します。 しばらくすると上の帯が緑になって、lambdaのセットアップが終わります。

右上のテストを定義し、実行してみると...

Hello world!!が返ってきました!

まとめ

ということで、オリジナルランタイムでの実行をまとめてみました。

公式ドキュメントではわざとalpine系を使ったり、Dockerのmulti stage buiidしたりしてややこしそうですが、実際はもっと簡単にできることが分かったと思います。

Lambdaは、最大コア数6、メモリ10GBまでの対応も発表されり激アツです。簡単な機械学習APIもより作りやすくなりました。
AWS Lambda now supports up to 10 GB of memory and 6 vCPU cores for Lambda Functions

非常に便利なので是非みなさんトライしてみてください!

次は、Detectron2という画像認識モデルをAWS Lambdaで動かしてみたいと思います!