【AWS入門者】だれでもできるLambda関数でDockerを利用
Lambda関数の作り方を学んだ後はさらにLambda関数でDockerを利用してみませんか?本文書ははじめてLambda関数でDockerを利用してみたいという人向けの内容になっています。
Python、Java、Node.js、Rubyなどを利用してLambda関数を作成することができますが本文書ではPythonを利用しています。
AWSでLambda関数を作成した経験がない人は下記の公開済みの文書を参考に作成してみてください。
目次
事前準備
macOSですでにDockerがインストールされている状態で開始します。もしDockerがインストールされていない場合は先にインストールを行ってください。インストールが完了している場合にはdockerコマンドを利用してバージョンを確認することができます。
% docker -v
Docker version 25.0.2, build 29cf629
% which docker
/Users/mac/.docker/bin/docker
動作確認を行うために任意の名前のディレクトリを作成します。
% mkdir aws_docker
動作確認
利用するDockerイメージ
AWS LambdaでPythonを実行するための公式のDockerイメージがあるためそのイメージを利用する必要があります。
今回利用するDockerイメージはpublic.ecr.aws/lambda/pytho:3.12です。ドキュメントのUsageを確認するとDockerイメージ/コンテナのローカルでの作成方法も記述されているのでその内容を参考に動作確認を行います。
こちらの記事も参考になります。
app.pyファイルの作成
aws_dockerディレクトリの下にDocker上で実行するapp.pyファイルを作成します。作成したapp.pyファイルに以下のコードを記述します。
import json
def lambda_handler(event, context):
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
Dockerfileの作成
aws_dockerディレクトリの下にDockerfileを作成します。
FROM public.ecr.aws/lambda/python:3.12
COPY app.py ${LAMBDA_TASK_ROOT}
CMD ["app.lambda_handler"]
FROMには利用するPythonのイメージ名を指定します。public.ecr.aws/lambda/python:3.12がAWSが提供するDockerイメージです。COPYでは作成したapp.pyファイルをイメージのファイルシステム上のパス(LAMDA_TASK_ROOT)にコピーしています。CMDはコンテナが起動する際に実行したい処理を指定します。Lambda関数を実行するとapp.pyファイルのlambda_handlerが実行されます。
イメージのビルド
dockerのコマンドを利用してDockerfileを元にイメージを作成します。
% docker build -t hello_from_lambda .
[+] Building 24.1s (7/7) FINISHED docker:desktop-linux
=> [internal] load build definition from Dockerfile
//略
What's Next?
View a summary of image vulnerabilities and recommendations → docker scout quickview
作成したイメージはdocker image lsコマンドで確認することができます。
% docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
hello_from_lambda latest fd6b985dabd3 About a minute ago 558MB
コンテナの作成、起動
作成したイメージを利用してローカルでLambda関数の動作確認を行うためにコンテナの作成、起動を行います。-pオプションでポートの指定を行っています。public.ecr.aws/lambda/python:3.12のイメージの中にLambda Runtime Interface Emulator(RIE)が含まれているためローカルでLambda関数の動作確認を行うことができます。RIE が8080ポートでリスニングをするためポートマッピングで 9000 ポートにマッピングしています。
% docker run -p 9000:8080 hello_from_lambda
14 Feb 2024 02:08:43,514 [INFO] (rapid) exec '/var/runtime/bootstrap' (cwd=/var/task, handler=)
実行するとhttp://localhost:9000/2015-03-31/functions/function/invocationsのエンドポイントが作成されます。ローカル環境の動作確認ではそのエンドポイントに対してcurlを利用してリクエストを送信します。
コンテナな実行後は、docker psコマンドで起動しているコンテナの情報を確認することができます。
% docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2cc186f6120a hello_from_lambda "/lambda-entrypoint.…" 16 minutes ago Up 1 minutes 0.0.0.0:9000->8080/tcp elegant_ritchie
コンテナの名前は指定をしていないので自動で命名されます。上記ではelegant_ritchieとなっており各自の環境によって名前が異なります。
起動しているコンテナへのログインは下記のコマンドで行うことができます。
% docker exec -it elegant_ritchie /bin/bash
ログイン後にlsコマンドを実行するとapp.pyファイルを確認することができます。pwdコマンドでは/var/taskにapp.pyファイルが作成されていることができます。
bash-5.2# ls
app.py
bash-5.2# pwd
/var/task
ログインした結果からDockerfileで利用した環境変数のLAMBDA_TASK_ROOTは/var/taskであることもわかりました。
Lamdba関数の実行
curlを実行してローカル環境でLambda関数を実行するために以下のコマンドを実行します。app.pyで記述した通りstatusCodeとbodyが戻されれば正常に動作しています。
% curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d {}
{"statusCode": 200, "body": "\"Hello from Lambda!\""}%
動作確認が完了したらコンテナを停止します。ここではコンテナ名はelegant_ritchieですがコンテナ名は各自の環境によって異なります。
% docker stop elegant_ritchie
elegant_ritchie
ECRのリポジトリの作成
Lambda関数はAWS ECR(Elastic Container Registry)に保存したDockerイメージを利用します。そのため作成したDockerイメージを保存するリポジトリの作成を行います。ここではリポジトリを作成して作成したイメージをアップロードします。
ECRにリポジトリを作成する前にECRにログインを行います。123456789012の部分を各自のAWSのアカウントIDに変更します。
% aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com
An error occurred (AccessDeniedException) when calling the GetAuthorizationToken operation: User: arn:aws:iam::123456789012:user/johndoe is not authorized to perform: ecr:GetAuthorizationToken on resource: * because no identity-based policy allows the ecr:GetAuthorizationToken action
Error: Cannot perform an interactive login from a non TTY device
IAMユーザに権限(ecr:GetAuthorizationToken)がない場合には上記のようにエラーメッセージが表示されます。
権限があり正しいコマンドで実行した場合には”Login Succeded”のメッセージが表示されます。
% aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com
Login Succeeded
権限がない場合はECRを利用できるポリシー”AmazonEC2ContainerRegistryFullAccess”をユーザにアタッチします。
ログイン完了後はcreate-repositoryコマンドを利用してhello_lambda_repoという名前のリポジトリを作成しています。リポジトリ名には任意の名前をつけることができます。ECRはプライベートとパブリック用のリポジトリを作成することができますが下記のコマンドではプライベート用のリポジトリを作成しています。
% aws ecr create-repository --repository-name hello_lambda_repo --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE
{
"repository": {
"repositoryArn": "arn:aws:ecr:ap-northeast-1:123456789012:repository/hello_from_lambda",
"registryId": "123456789012",
"repositoryName": "hello_lambda_repo",
"repositoryUri": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/hello_from_lambda",
"createdAt": "2024-02-14T13:13:18.831000+09:00",
"imageTagMutability": "MUTABLE",
"imageScanningConfiguration": {
"scanOnPush": true
},
"encryptionConfiguration": {
"encryptionType": "AES256"
}
}
}
作成後はdescribe-repositoriesで作成したリポジトリの情報を確認することができます。
% aws ecr describe-repositories
{
"repository": {
"repositoryArn": "arn:aws:ecr:ap-northeast-1:123456789012:repository/hello_from_lambda",
"registryId": "123456789012",
"repositoryName": "hello_lambda_repo",
"repositoryUri": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/hello_from_lambda",
"createdAt": "2024-02-14T13:13:18.831000+09:00",
"imageTagMutability": "MUTABLE",
"imageScanningConfiguration": {
"scanOnPush": true
},
"encryptionConfiguration": {
"encryptionType": "AES256"
}
}
}
リポジトリを作成後は作成済みのイメージにタグをつけるためdocker tagコマンドを実行します。イメージをECRにアップロードするためにはタグ付けは必須です。123456789012の箇所は各自のAWSのアカウントIDを指定してください。
% docker tag hello_from_lambda:latest 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/hello_lambda_repo:latest
//書式
% docker tag イメージ名: 作成したECRのリポジトリ名:
docker tagを実行後にdocker imagesコマンドを実行すると名前の異なる2つのイメージが同じIDで作成されていることがわかります。
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/hello_lambda_repo latest 0706fcaa0e46 1 hours ago 558MB
hello_from_lambda latest 0706fcaa0e46 1 hours ago 558MB
タグ付けしたイメージのアップロードにはdocker pushコマンドを利用します。タグづけ後に作成されているイメージの名前を指定してください。
% docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/hello_lambda_repo:latest
The push refers to repository [123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/hello_lambda_repo]
da20c8544dac: Pushed
b2fbcdbc3abe: Pushed
01237e4b624b: Pushed
7393ae547845: Pushed
08352d8f528a: Pushed
4ad08681a382: Pushed
8a302ef602af: Pushed
latest: digest: sha256:0f82092ea1df081186fd83788f50fc8629a223ebd13d1b8699a4b33a5cb14f size: 1785
アップしたイメージの情報をManagement ConsoleのECRのサービスから確認することができます。
Lambda関数の作成
ECRにイメージがアップロードできたらいよいよDockerのイメージを利用してLambda関数の作成を行います。
Management ConsoleからLambda関数を作成します。
関数の作成画面のオプションではコンテナイメージを選択してください。コンテナイメージを選択するとイメージを参照ボタンから作成したリポジトリのイメージが選択できるようになるので選択してください。名前はhelloLambdaとしています。
動作確認でLambda関数から別のサービスを利用するわけではないので設定するロールがない場合はロールには基本的なLambdaアクセス権限で新しいロールを作成を選択してください。自動で命名されたロールが追加されて設定されます。
関数の作成ボタンをクリックするとhelloLambdaという名前のLambda関数が作成されます。Management Consoleからでもテストは実施できますが、作成したLambda関数をAWS CLIコマンドを利用して実行します。
% aws lambda invoke --function-name helloLambda response.json
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
response.jsonファイルには関数の戻り値が保存されているので中身を確認します。
{"statusCode": 200, "body": "\"Hello from Lambda!\""}
Dockerを利用して作成したLambda関数を実行することができました。簡単なPythonファイルの実行でしたが作成方法は理解できたと思うので次はDockerで実行させる内容を高度なものにしてチャレンジしてみてください。