この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
データアナリティクス事業本部の鈴木です。
Rancher Desktopをインストールしたローカル環境からAmazon ECRにコンテナイメージを準備して、AWS Lambdaで実行してみたので、試した内容をまとめてみました。
検証の内容
今回は簡単に、以下の3点を確認しました。
- AWS CDKでECRにレポジトリを作成する。
- dockerコマンドでECRのレポジトリにコンテナイメージをpushする。
- コンテナをLambdaで実行する。
ECRのレポジトリにコンテナイメージを上げておくと、Lambdaはもちろん、ECSやSageMakerなどのさまざまなサービスによりコンテナを利用することができます。
今回はその例の一つとして、簡単ではありますが、レポジトリの作成からLambdaでの実行までを試してみました。
環境
以下の環境で検証しました。
- Rancher Desktop:
Version: 1.8.1
- AWS CDK:
2.73.0
特にRancher Desktopについては、以下の記事ような手順であらかじめインストールしておきました。
やってみる
1. ECRレポジトリの作成
まず、以下のようにプロジェクトを作成しました。
mkdir cdk_erc
cd cdk_erc
cdk init sample-app --language typescript
lib/cdk_erc-stack.ts
は以下のようにしました。
lib/cdk_erc-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as ecr from "aws-cdk-lib/aws-ecr";
import { Construct } from 'constructs';
export class CdkErcStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// ECRレポジトリ
const lambdaEcrRepository = new ecr.Repository(this, 'Repository', {
repositoryName: "cm-nayuts-sample-repo",
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteImages: true
});
}
}
今回はレポジトリを削除しやすいように、removalPolicy
とautoDeleteImages
に値を設定してみました。ただし、運用する際は間違って消えてしまう可能性もあるので注意が必要です。
cdk deploy
でデプロイします。私の環境ではconfigファイルで指定したプロファイルでAWS環境にアクセスするようにしているので、--profile
オプションを付けました。
cdk deploy --profile プロファイル名
--profile
オプションについては、AWS CDK Toolkit (cdk command) - AWS Cloud Development Kit (AWS CDK) v2のSpecifying Region and other configurationをご確認ください。
以下のように作成されました。
リポジトリタグも設定されています。
2. コンテナイメージのpush
プロジェクトのルートにdocker
ディレクトリとsrc
ディレクトリを作成しました。
以下のようになるよう、ファイルを配置しました。
cd docker
tree
# docker
# ├── docker_build.sh
# └── dockerfile
cd lambda
tree
# src
# ├── app.py
# └── requirements.txt
以下は作成したファイルの説明です。
なお、app.py
およびdockerfile
は、2023/4/9時点でAWS Lambdaデベロッパーガイドのコンテナイメージで Python Lambda 関数をデプロイするに記載の内容を使用させて頂きました。
docker_build.sh
これはdockerfileからコンテナイメージをビルドしてECRにpushするツールです。
docker_build.sh
#!/bin/bash
ACCOUNTID=${1}
REGION=${2}
ECR_REPO_NAME=${3}
AWS_PROFILE=${4}
ECR_REPO_URI="${ACCOUNTID}.dkr.ecr.${REGION}.amazonaws.com/${ECR_REPO_NAME}"
echo "ECR_REPO_URI: ${ECR_REPO_URI}"
aws ecr get-login-password --region ${REGION} --profile ${AWS_PROFILE} | docker login --username AWS --password-stdin ${ACCOUNTID}.dkr.ecr.${REGION}.amazonaws.com
docker build -f ./docker/dockerfile -t ${ECR_REPO_NAME} .
docker tag ${ECR_REPO_NAME}:latest ${ECR_REPO_URI}:latest
docker push ${ECR_REPO_URI}:latest
dockerfile
デベロッパーガイド記載の、Python関数のコンテナイメージ作成用のdockerfileです。
dockerfile
FROM public.ecr.aws/lambda/python:3.8
# Install the function's dependencies using file requirements.txt
# from your project folder.
COPY ./src/requirements.txt .
RUN pip3 install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"
# Copy function code
COPY ./src/app.py ${LAMBDA_TASK_ROOT}
# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "app.handler" ]
app.py
デベロッパーガイド記載の、Python関数で実行するスクリプトです。
app.py
import sys
def handler(event, context):
return 'Hello from AWS Lambda using Python' + sys.version + '!'
requirements.txt
コンテナイメージのビルド時にインストールするPythonライブラリの一覧です。今回は特に必要がないので空ファイルにしておきました。
ここまでで、プロジェクトは以下のようなディレクトリ構成になっています。
tree -L 1
# .
# ├── README.md
# ├── bin
# ├── cdk.json
# ├── docker
# ├── jest.config.js
# ├── lib
# ├── node_modules
# ├── package-lock.json
# ├── package.json
# ├── src
# ├── test
# └── tsconfig.json
プロジェクトのルートから、以下のようにツールを実行して、コンテナイメージをECRのレポジトリにpushしました。
./docker_build.sh 自分のAWSアカウントID ap-northeast-1 レポジトリ名 プロファイル名
このようにイメージがpushされました。
3. Lambdaでの実行
pushしたコンテナイメージを、Lambdaでコンテナとして実行してみました。Lambdaは別のCDKのプロジェクトを作ってデプロイしました。
mkdir cdk_lambda
cd cdk_lambda
cdk init sample-app --language typescript
lib/cdk_lambda-stack.ts
は以下のようにしました。
lib/cdk_erc-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as ecr from "aws-cdk-lib/aws-ecr";
import * as lambda from "aws-cdk-lib/aws-lambda";
import { Construct } from 'constructs';
export class CdkLambdaStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// ECRリポジトリARNを指定して、Lambda関数用カスタムコンテナイメージのリポジトリを取得する。
const lambdaEcrRepository = ecr.Repository.fromRepositoryArn(
this,
id,
this.node.tryGetContext("ecrRepoArn")
);
// Python関数
const sampleLambda = new lambda.Function(this, "cm-nayuts-sample-container-lambda", {
code: lambda.Code.fromEcrImage(lambdaEcrRepository, {
cmd: ["app.handler"],
tag: "latest",
}),
functionName: "cm-nayuts-sample-container-lambda",
runtime: lambda.Runtime.FROM_IMAGE,
handler: lambda.Handler.FROM_IMAGE,
timeout: cdk.Duration.seconds(3)
});
}
}
ECRリポジトリのARNは、cdk.json
のcontext
に、ecrRepoArn
のバリューとして設定しておきました。
そして、以下のコマンドでデプロイしました。
cdk deploy --profile プロファイル名
以下のように関数が作成されました。
テストから実行してみると、app.py
が実行されていることが分かりました。
後片付け
それぞれのCDKプロジェクトで、スタックを削除しておきました。
cdk destroy --profile プロファイル名
ECRのレポジトリもリポジトリタグの効果でスタックを削除すると綺麗に削除されました。検証時は便利ですが、運用時は間違って消される可能性もありそうなのでそこは注意ですね。
最後に
Rancher Desktopをインストールしたローカル環境から、Amazon ECRにコンテナイメージを準備してAWS Lambdaで実行してみたので、試した内容をまとめてみました。
簡単な例ではありましたが、Lambdaで実行するコンテナを変えればさまざまなことが実現できますし、ECRにpushする方法まで分かったのでSageMakerのProcessing Jobを使うときなどにも応用ができますね。