エンジニアのはしがき

プログラミングの日々の知見を書き連ねているブログです

AWS LambdaでDockerコンテナを動かす

f:id:tansantktk:20211023153421j:plain

こんばんは!DockerコンテナでごにょごにょしてLambda環境で実行させたいなぁと以前から思ってたので、今回やっと手を出してみました。

はじめに

当記事で解説する内容はほぼAWS公式の以下の内容となります。

docs.aws.amazon.com

やりたいこと

  • AWS Lambda上でDockerコンテナ(Python)を実行したい

開発環境

Dockerエンジンは既にインストールされているものとします。

$ cat /etc/os-release 
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"

$ docker --version
Docker version 20.10.4, build d3cb89e

コンテナ内で実行するソースコード

今回は例として何の変哲もないHello, worldするだけのコードを実行させます。 注意すべき点は、ファイル名をapp.py、Lambda起動時に呼び出す対象となるメソッド名をhandler命名する必要があるところです。これを忘れるとハマります。

app.py

def handler(event, context):
    print('hello, world')
    return {
        'isBase64Encoded': False,
        'statusCode': 200,
        'headers': {},
        'body': 'ok'
    }

Dockerfileを作成

次にAWSが配布しているpython用のコンテナをベースイメージに指定してDockerfileを作成します。

COPYでローカルのapp.pyをコンテナイメージ側にコピーしていますが、この時のイメージ側のパスは${LAMBDA_TASK_ROOT}(=/var/task)を指定する必要があります。

その次のCMDでは、app.pyhandlerメソッドを呼び出すよう指定します。これも忘れるとソースコードが実行されませんので注意です。

FROM public.ecr.aws/lambda/python:3.9
# LAMBDA_TASK_ROOTはLambdaの環境変数で/var/taskを指す
COPY app.py ${LAMBDA_TASK_ROOT}
# Lambda起動時に実行するメソッドを指定
CMD ["app.handler"]

ECRにコンテナイメージをpushする

AWSコンソールからECRのリポジトリ一覧を開き、新規にリポジトリを作成した後、ローカルからECRへコンテナイメージをpushします。

pushまでのコマンドはリポジトリ画面の「プッシュコマンドの表示」を押せば、全て確認できるので指示に従ってpushしましょう。

f:id:tansantktk:20211003221511p:plain

Lambda関数を作成する

新規作成画面で「コンテナイメージ」を選択すると、コンテナイメージを入力する入力フォームが出てきますので、ECRにpushしたイメージを指定してLambdaを作成します。

f:id:tansantktk:20211003221718p:plain

テスト

準備が出来たのでちゃんと動作するかAWSコンソール上からLambdaのテストを実行します。

f:id:tansantktk:20211003221923p:plain

正常に動作していれば、テスト結果のログにhello, worldが出力されるはずです。

構築までにハマったこと

最初に作り出した時は、DockefileのCOPYで指定するコンテナ側のパスを${LAMBDA_TASK_ROOT}以外に指定していたり、ファイル名をapp.pyにしていなかったりしていた為、実行時にエラーが多発してなかなか苦戦しました。

最終的にAWS公式のドキュメントを見て解決し、ドキュメントの重要性を再確認しました。横着してはいかん…。