コンテナイメージを使用して Go Lambda 関数をデプロイする - AWS Lambda

コンテナイメージを使用して Go Lambda 関数をデプロイする

Lambda 関数コードをコンテナイメージとしてデプロイできます。Go 関数のコンテナイメージの構築を支援するため、AWS は次のリソースを提供します。

  • Lambda の AWS ベースイメージ

    これらのベースイメージには、Lambda でイメージを実行するために必要な言語ランタイムおよびその他のコンポーネントがプリロードされています。AWS は、コンテナイメージの構築に役立つ各ベースイメージの Dockerfile を提供します。

  • オープンソースのランタイムインターフェイスクライアント

    コミュニティまたはプライベートエンタープライズのベースイメージを使用する場合、ランタイムインターフェイスクライアントをベースイメージに追加し、Lambda と互換性を持たせる必要があります。

  • オープンソースのランタイムインターフェイスエミュレータ

    Lambda は、関数をローカルでテストするためのランタイムインターフェイスエミュレータ(RIE)を提供します。Lambda のベースイメージおよびカスタムランタイムのベースイメージには RIE が含まれます。その他のベースイメージでは、イメージをローカルでテストするための RIE をダウンロードできます。

コンテナイメージとして定義された関数のワークフローには、次のステップが含まれます。

  1. このトピックにリストされているリソースを使ってコンテナイメージを構築します。

  2. Amazon Elastic Container Registry (Amazon ECR) のコンテナレジストリ にイメージをアップロードします。

  3. 関数を作成するか、関数コードを更新し、イメージを既存の関数にデプロイします。

AWSGo 用の ベースイメージ

AWS では、次のような Go に使用できるベースイメージを提供しています。

タグ ランタイム オペレーティングシステム Dockerfile 廃止

1

Go 1.x Amazon Linux GitHub 上の Go 1.x 用の Dockerfile

Amazon ECR リポジトリ: gallery.ecr.aws/lambda/go

Go 用ランタイムインターフェイスクライアント

AWS では、Go 用として、個別のランタイムインターフェイスクライアントは提供していません。aws-lambda-go/lambda パッケージには、ランタイムインターフェイスの実装が含まれています。

Go:1.x ベースイメージの使用

このセクションの手順を完了するには、以下が必要です。

  1. プロジェクト用のディレクトリを作成し、そのディレクトリに切り替えます。

    mkdir hello cd hello
  2. 新しい Go モジュールを初期化します。

    go mod init example.com/hello-world
  3. Lambda ライブラリを新しいモジュールの依存関係として追加します。

    go get github.com/aws/aws-lambda-go/lambda
  4. hello.go」という名前のファイルを作成し、テキストエディタで開きます。これは Lambda 関数のコードです。次のサンプルコードをテストに使用することも、独自のサンプルコードで置き換えることもできます。

    package main import ( "context" "fmt" "github.com/aws/aws-lambda-go/lambda" ) type MyEvent struct { Name string `json:"name"` } func HandleRequest(ctx context.Context, name MyEvent) (string, error) { return fmt.Sprintf("Hello %s!", name.Name), nil } func main() { lambda.Start(HandleRequest) }
  5. Go プロジェクトを構築します。このコマンドは、「main」という実行可能ファイルを作成します。

    GOOS=linux GOARCH=amd64 go build -o main hello.go

    GOOSlinux に設定し、GOARCHamd64 に設定すると、非 Linux 環境でコンパイルする場合でも、コンパイルされた実行可能ファイルに Go ベースイメージのアーキテクチャと互換性を持たせられます。

  6. 新しい Dockerfile を作成します。Dockerfile の例は次の設定を使用します。

    • FROM: 使用する「ベースイメージの URI」。

    • COPY: 関数コードをイメージの「/var/task」ディレクトリにコピーします。

    • CMD: Lambda 関数ハンドラーまたは実行可能ファイル。

    FROM public.ecr.aws/lambda/go:1 # Copy function code COPY main ${LAMBDA_TASK_ROOT} # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile) CMD [ "main" ]
  7. Docker イメージを「Docker の構築」コマンドで構築します。次の例では、イメージを docker-image と名付けて test タグを付けます。

    docker build -t docker-image:test .
(オプション) イメージをローカルでテストする
  1. docker run コマンドを使用して Docker イメージを起動します。この例では、docker-image はイメージ名、test はタグです。

    docker run -p 9000:8080 docker-image:test

    このコマンドはイメージをコンテナとして実行し、localhost:9000/2015-03-31/functions/function/invocations でローカルエンドポイントを作成します。

  2. RIE を使用して、アプリケーションをローカルでテストします。新しいターミナルウィンドウから curl コマンドを使用して、次のエンドポイントにイベントをポストします。

    curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"Name": "World"}'

    このコマンドは、コンテナイメージで実行されている 関数を呼び出し、応答を返します。

  3. コンテナ ID を取得します。

    docker ps
  4. docker kill」コマンドを使用してコンテナを停止します。このコマンドでは、3766c4ab331c を前のステップのコンテナ ID で置き換えます。

    docker kill 3766c4ab331c
Amazon ECR にイメージをアップロードして Lambda 関数を作成するには
  1. get-login-password」コマンドを実行して Amazon ECR レジストリに Docker CLI を認証します。

    • --region 値を Amazon ECR リポジトリを作成する AWS リージョン に設定します。

    • 111122223333 を AWS アカウント ID に置き換えます。

    aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-east-1.amazonaws.com
  2. create-repository」コマンドを使用して Amazon ECR にリポジトリを作成します。

    aws ecr create-repository --repository-name hello-world --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE

    成功すると、次のようなレスポンスが表示されます。

    { "repository": { "repositoryArn": "arn:aws:ecr:us-east-1:111122223333:repository/hello-world", "registryId": "111122223333", "repositoryName": "hello-world", "repositoryUri": "111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world", "createdAt": "2023-03-09T10:39:01+00:00", "imageTagMutability": "MUTABLE", "imageScanningConfiguration": { "scanOnPush": true }, "encryptionConfiguration": { "encryptionType": "AES256" } } }
  3. 前のステップの出力から repositoryUri をコピーします。

  4. docker tag」コマンドを実行して、最新バージョンとしてローカルイメージを Amazon ECR リポジトリにタグ付けします。このコマンドで:

    • docker-image:test をお使いの Docker イメージの名前およびタグで置き換えます。

    • Amazon ECR リポジトリ URI をコピーした repositoryUri で置き換えます。URI の末尾には必ず :latest を含めてください。

    docker tag docker-image:test 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
  5. docker push」コマンドを実行して Amazon ECR リポジトリにローカルイメージをデプロイします リポジトリ URI の末尾には必ず :latest を含めてください。

    docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
  6. まだ作成済みでない場合、関数に「実行ロールの作成」を実行してください。次のステップではロールの Amazon リソースネーム (ARN) が必要です。

  7. Lambda 関数を作成する ImageUri には、先ほど使用したリポジトリ URI を指定します。URI の末尾には必ず :latest を含めてください。

    aws lambda create-function \ --function-name hello-world \ --package-type Image \ --code ImageUri=111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \ --role arn:aws:iam::111122223333:role/lambda-ex
  8. 関数を呼び出します。

    aws lambda invoke --function-name hello-world response.json

    次のような結果が表示されます。

    { "ExecutedVersion": "$LATEST", "StatusCode": 200 }
  9. 関数の出力を確認するには、response.json ファイルを確認してください。

関数コードを更新するには、新しいバージョンのイメージを作成し、そのイメージを Amazon ECR リポジトリに保存する必要があります。詳細については、「関数コードの更新」を参照してください。

provided.al2 ベースイメージから Go イメージを作成する

Amazon Linux 2 で実行される Go のコンテナイメージを作成するには、provided.al2 ベースイメージを使用します。このベースイメージの詳細については、Amazon ECR Public Gallery の「provided」を参照してください。

aws-lambda-go/lambda パッケージを Go ハンドラーにインクルードします。このパッケージにより、ランタイムインターフェイスクライアントを含む、Go のプログラミングモデルが実装されます。provided.al2 ベースイメージには RIE も含まれます。

provided.al2 ベースイメージを使用しながら、Go 関数をビルドしデプロイします。
  1. プロジェクト用のディレクトリを作成し、そのディレクトリに切り替えます。

    mkdir hello cd hello
  2. 新しい Go モジュールを初期化します。

    go mod init example.com/hello-world
  3. Lambda ライブラリを新しいモジュールの依存関係として追加します。

    go get github.com/aws/aws-lambda-go/lambda
  4. hello.go」という名前のファイルを作成し、テキストエディタで開きます。これは Lambda 関数のコードです。次のサンプルコードをテストに使用することも、独自のサンプルコードで置き換えることもできます。

    package main import ( "context" "fmt" "github.com/aws/aws-lambda-go/lambda" ) type MyEvent struct { Name string `json:"name"` } func HandleRequest(_ context.Context, name MyEvent) (string, error) { return fmt.Sprintf("Hello %s!", name.Name), nil } func main() { lambda.Start(HandleRequest) }
  5. テキストエディタを使用して、プロジェクトディレクトリに Dockerfile を作成します。次の Dockerfile の例では、「マルチステージビルド」が使用されます。これにより、各ステップで異なるベースイメージを使用できます。「Go ベースイメージ」など、1 つのイメージを使用し、コードをコンパイルして実行可能なバイナリを構築できます。その後、最後の FROM ステートメントで provided.al2 など別のイメージを使用し、Lambda にデプロイするイメージを定義できます。ビルドプロセスは最終デプロイイメージとは分離されているため、最終イメージにはアプリケーションの実行に必要なファイルのみが含まれます。

    例 — マルチステージビルド Dockerfile
    注記

    Dockerfile で指定する Go のバージョン (たとえば、golang:1.20) が、アプリケーションの作成に使用した Go のバージョンと同じであることを確認してください。

    FROM golang:1.20 as build WORKDIR /helloworld # Copy dependencies list COPY go.mod go.sum ./ # build COPY hello.go . RUN go build -o main hello.go # copy artifacts to a clean image FROM public.ecr.aws/lambda/provided:al2 COPY --from=build /helloworld/main /main ENTRYPOINT [ "/main" ]
  6. docker build コマンドを使用して Docker イメージをビルドします。次の例では、イメージに docker-image という名前を付けています。

    docker build -t docker-image:test .
  7. イメージを Amazon ECR にデプロイし Lambda 関数を作成します

代替ベースイメージから Go イメージを作成する

代替のベースイメージからも、Go 用のコンテナイメージを構築できます。次の Dockerfile の例では、ベースイメージとして alpine を使用しています。

例 アルパインベースイメージを含む Dockerfile
注記

Dockerfile で指定する Go のバージョン (たとえば、golang:1.20.2) が、アプリケーションの作成に使用した Go のバージョンと同じであることを確認してください。

FROM golang:1.20.2-alpine3.16 as build WORKDIR /helloworld # Copy dependencies list COPY go.mod go.sum ./ # Build COPY hello.go . RUN go build -o main hello.go # Copy artifacts to a clean image FROM alpine:3.16 COPY --from=build /helloworld/main /main ENTRYPOINT [ "/main" ]

手順は provided.al2 ベースイメージの手順 と同じですが、もう 1 つの考慮事項があります。イメージに RIE を追加する場合、docker build コマンドを実行する前に、これらの追加手順に従う必要があります。RIE を使用してイメージをローカルにテストする方法の詳細については、「Lambda コンテナイメージをローカルでテストする」を参照してください。

イメージに RIE を追加するには、
  1. Dockerfile で、ENTRYPOINT 命令を次の内容に置き換えます。

    # (Optional) Add Lambda Runtime Interface Emulator and use a script in the ENTRYPOINT for simpler local runs ADD https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie /usr/bin/aws-lambda-rie RUN chmod 755 /usr/bin/aws-lambda-rie COPY entry.sh / RUN chmod 755 /entry.sh ENTRYPOINT [ "/entry.sh" ]
  2. テキストエディタを使用して、プロジェクトディレクトリに entry.sh という名前で、次の内容のファイルを作成します。

    #!/bin/sh if [ -z "${AWS_LAMBDA_RUNTIME_API}" ]; then exec /usr/bin/aws-lambda-rie "$@" else exec "$@" fi

イメージに RIE を追加する必要がない場合は、RIE なしでもローカルでテストできます。

イメージに RIE を追加せずにローカルでテストするには、
  1. プロジェクトディレクトリから次のコマンドを実行して、GitHub から RIE をダウンロードし、ローカルマシンにインストールします。

    mkdir -p ~/.aws-lambda-rie && curl -Lo ~/.aws-lambda-rie/aws-lambda-rie \ https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie \ && chmod +x ~/.aws-lambda-rie/aws-lambda-rie
  2. docker run コマンドを使用して、Lambda イメージの関数を実行します。次の例では、/main が関数のエントリポイントへのパスとなっています。

    docker run -d -v ~/.aws-lambda-rie:/aws-lambda --entrypoint /aws-lambda/aws-lambda-rie -p 9000:8080 myfunction:latest /main

    このコマンドはイメージをコンテナとして実行し、ローカルの localhost:9000/2015-03-31/functions/function/invocations でエンドポイントを起動します。

  3. curl コマンドを使用して、次のエンドポイントにイベントをポストします。

    curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"Name": "World"}'

    このコマンドは、コンテナイメージで実行されている 関数を呼び出し、応答を返します。

  4. イメージを Amazon ECR にデプロイし Lambda 関数を作成します