0
0

More than 3 years have passed since last update.

AWS LambdaのDocker Container ImageをPerlでやっていく

Posted at

結構引っかかったのでメモ。

Lambda用のPerl Container

コンテナ自体はshogoさんが動くものを置いていただいているのでそれをベースイメージとすればよい。感謝感謝。
自分で作る手順も書いてあるのでこんどやる。

手順としては、まず 上記のコンテナをFROMとして Dockerfile をつくりECRにビルドしてpush、そしてビルドしたECRのイメージをLambdaで使うという設定をすればよい。

実際にやってみる

だいたいコピペ。
ECRとかLambdaのIAMとかは適宜作ってください。

以下の Dockerfile を用意。


FROM public.ecr.aws/w2s0h5h2/p5-aws-lambda:base-5.32-paws.al2
COPY handler.pl /var/task/
CMD [ "handler.handle" ]

以下の handler.pl を用意

handler.pl
use utf8;
use warnings;
use strict;
$| = 1;

sub handle {
    my $payload = shift;
    print "log test from perl";
    warn "test";
    return +{"hello" => "lambda"};
}

1;

以下のようなビルドスクリプトがあるといい感じかもしれない。
ローカルでビルドしたimagesとsha256が同じやつがECRにいないかをチェックして
いなければECRにpushするということをやる。

run.sh
APP=xxx
REPO=$(aws ecr describe-repositories --repository-names $APP --query "repositories[0].repositoryUri" --output text | perl -pe '$_ = (split "/")[0]')
DATE=$(date '+%Y%m%d_%H%M%S')

docker build . -t $APP
docker tag "$APP:latest" "$REPO/$APP:$DATE"

LOCAL_BUILD=$(docker inspect $APP | jq '.[0].RepoDigests[0] | split("@")[1]' -r)
REMOTE_BUILDS=$(aws ecr list-images --repository-name $APP | jq '.imageIds[].imageDigest' -r)

REMOTE_COUNT=$(echo "$REMOTE_BUILDS" | sort | uniq | wc -l)
ALL_COUNT=$(echo "$LOCAL_BUILD\n$REMOTE_BUILDS" | sort | uniq | wc -l)

if [ $ALL_COUNT = $REMOTE_COUNT ]; then
    echo "build is same. skipping..."
else
    echo "build is different. push to ecr..."
    aws ecr get-login-password | docker login --username AWS --password-stdin $REPO
    docker push "$REPO/$APP:$DATE"
fi

ゆくゆくはCIもやりましょう。

はまったこと・注意すること

標準出力のflushをオンにする。

Perlにおいては $| = 1 をやればよい。

自作のコンテナでlambdaを動かす場合は、標準出力がバッファリングされないように設定しないとCloudwatch Logsに出ないっぽい。rubyのコンテナを参考にしたところ、標準出力をflushにしていたので倣ったところ出るようになった。

最初普通に print をやっても出力されず、warnをやったら出力されたのでピンときた。
もしかして自作コンテナだとログは自分で CloudWatch Logsの PutLogEvents を呼ばないとだめなのか?と思ったけどそうじゃなくてよかった。

なお、Lambda上だとSTDOUTとSTDERRが一緒くたに扱われる上に、バッファリングがオフにしないといけないので

print 123;
warn 456

のようなコードが

123456 at /var/task/handler.pl line 9.

と出力されるので一瞬びっくりするかもしれない。
loggerのライブラリを使うべきで素のwarnとかprintは使うべきではないっぽいですね。

CloudWatchのログ出力名は関数名と同じ

たとえばLambdaの関数名を moge とした場合、
作成されるCloudWatch Logsのロググループ名は /aws/lambda/moge 固定。

serverlessみたいなフレームワークにまかせっきりにしてたことなので知りませんでしたね。
名前が固定されているからといって何もせずにログが出るということはなく、下記みたいな権限設定が必要なのも忘れずに。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Action": "logs:CreateLogStream",
            "Resource": "arn:aws:logs:ap-northeast-1:000000000000:log-group:/aws/lambda/moge:*"
        },
        {
            "Sid": "2",
            "Effect": "Allow",
            "Action": "logs:PutLogEvents",
            "Resource": "arn:aws:logs:ap-northeast-1:000000000000:log-group:/aws/lambda/moge:*:*"
        }
    ]
}

まとめ

しかし、lambda docker で検索するとローカルでのlambdaの開発をdockerでやるみたいな話がいっぱい出てきて、lambdaをDocker containerで動かす話のググラビリティが低くて困る。どう検索したらいいんでしょうね。

上記文を書いて思ったけど、全然前者と後者の区別がつかないねこれ。

LambdaのDocker Containerの開発自体は、さすがにserverlessみたいなフレームワークほど手軽ではないものの、いうほど大変でないのでとてもよいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0