LoginSignup
2
1

zio-lambdaでnativeで動くaws lambda関数を書く方法【2024年版】

Last updated at Posted at 2024-03-13

zio-lambda を使うと、GraalVMでnative-imageを作成し、それをaws lambdaで呼び出せるようになります。便利ですね。

ただ、ドキュメント等が若干古いので、2024年におけるサンプルを下記に示します。

下準備

下記を用意します。

project/build.properties
sbt.version=1.9.9
build.sbt
lazy val root = (project in file("."))
  .settings(
    organization := "com.hoge",
    name := "zio-lambda-test",
    scalaVersion := "3.3.3",
    libraryDependencies ++= Seq(
      "dev.zio" %% "zio-json" % "0.6.2",
      "dev.zio" %% "zio-lambda" % "1.0.4"
    )
  )
  // ネイティブビルド関連の設定
  .enablePlugins(GraalVMNativeImagePlugin)
  .settings(
    GraalVMNativeImage / mainClass := Some("com.hoge.SimpleHandler"),
    GraalVMNativeImage / containerBuildImage := Some("ghcr.io/graalvm/native-image-community:21.0.2"),
    graalVMNativeImageOptions := Seq(
      "--verbose",
      "--no-fallback",
      "--install-exit-handlers",
      "--enable-http",
      "--link-at-build-time",
      "--report-unsupported-elements-at-runtime",
      "-H:+UnlockExperimentalVMOptions",
      "-H:+StaticExecutableWithDynamicLibC",
      "-H:+RemoveSaturatedTypeFlows"
    )
  )
project/plugins.sbt
addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.9.9")

設定はzio-lambdaのbuild.sbtから拝借しています。zio-lambdaとしてはnative-imageの作成方法について指定していないので、sbt-native-imageでも構いません。

Scalaは最新LTSの3.3.3を使います。そのためにはzio-jsonの最新バージョンを使う必要があります(詳細は下記issueを参照)。

ドキュメントではgraalvm-ceを使っていましたが、native-imageを使えるdockerイメージが用意されたので、containerBuildImageにはnative-imageを直接指定しています。

ソースコード

とりあえずHello Worldを書きます。

src/main/scala/com/hoge/SimpleHandler.scala
package com.hoge

import zio.Console._
import zio._
import zio.lambda._

object SimpleHandler extends ZIOAppDefault {

  val app = (event: CustomEvent, _: Context) =>
    for {
      _ <- printLine(event.message)
    } yield "Handler ran successfully"

  override val run =
    ZLambdaRunner.serve(app)
}
src/main/scala/com/hoge/CustomEvent.scala
package com.hoge

import zio.json._

final case class CustomEvent(message: String)

object CustomEvent {
  implicit val decoder: JsonDecoder[CustomEvent] = DeriveJsonDecoder.gen[CustomEvent]
}
src/main/scala/com/hoge/CustomResponse.scala
package com.hoge

import zio.json._

final case class CustomResponse(message: String)

object CustomResponse {
  implicit val encoder: JsonEncoder[CustomResponse] = DeriveJsonEncoder.gen[CustomResponse]
}

実際にはCustomResponseは使われていませんが、とりあえずサンプルにあったのでコピっておきます。

ビルド

ネイティブイメージを作成します。

sbt GraalVMNativeImage/packageBin

zipファイルでデプロイする場合

bootstrapファイルを作成します。ファイル名はbootstrap以外にすることはできません。

target/graalvm-native-image/bootstrap
#!/usr/bin/env bash

set -euo pipefail

./zio-lambda-test

zipに固めます。

cd target/graalvm-native-image
zip upload.zip bootstrap zio-lambda-test

固めたupload.zipをaws lambdaにアップロードすると、実行できます。

dockerイメージに固める場合

先にaws ecrにアップロード先のリポジトリを作っておきます。

次にdockerイメージをビルドしてプッシュします。

FROM gcr.io/distroless/base-debian12
COPY target/graalvm-native-image/zio-lambda-test /app/zio-lambda-test
CMD ["/app/zio-lambda-test"]

ベースイメージはbase-debian12にする必要があります。

pass=$(aws ecr get-login-password --region us-east-1) 
docker login --username AWS --password $pass <your_AWS_ECR_REPO>   
docker tag native-image-binary <your-particular-ecr-image-repository>:<your-tag>
docker push <your-particular-ecr-image-repository>:<your-tag>

プッシュしたdockerイメージを指定してaws lambdaを作成すると、実行できます。

注意点

native-imageでビルドしているため、アーキテクチャがローカルPCのアーキテクチャに依存しています。そのため、lambdaのアーキテクチャはローカルPCのアーキテクチャと一致させる必要があります。

追記

上記内容をg8テンプレートで作りました。サクッとラムダ書いてみたくなった方、どうぞ。

sbt new kijuky/zio-lambda.g8

追記2

変更内容がマージされました。

2
1
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
2
1