LambdaのContainer Image Supportでサブコマンド経由で呼ぶ方法
2020/12、Lambdaに待望のコンテナイメージサポートが追加されました。これにより、すでにECSなどでコンテナベースのデプロイをしている場合は既存のイメービルドの仕組みを流用できるようになりました。
同時にローカル環境でLambda関数をAPI経由で実行可能にするThe Lambda Runtime Interface Emulator (“RIE”)も公開されました。
実はDockerfileのCMDでサブコマンドを指定してLambda関数を呼び出す場合、RIEとAWS実環境で挙動が異なることがわかりました。
今回は両方で動く方法を実装して https://github.com/nabeken/go-lambda-subcommands-example に公開しています。
どういうこと
イメージサイズを小さく保つため、Goで複数のコマンド(e.g. APIやworker)を書く時はシングルバイナリにして、実際のコマンドはサブコマンドとして実装することが多いです。
例:
prj-main api
prj-main worker-foobar
prj-main
がビルドされたバイナリで、実際のコマンドは引数で指定。
これをLambdaのContainer Image Supportで行なう場合は Dockerfile
の CMD ["prj-main", "api"]
のように指定しますが、RIEではこれが動きません。
推測ですが、RIEは従来のLambda関数のパッケージングもサポートする関係上、 _HANDLER
環境引数に指定されたバイナリを実行しようとします。この値はファイル名であることを期待しているため、引数が渡せません。
上のサンプルプロジェクトに含まれる entrypoint.sh と _lambda_main はオリジナルの引数をファイルへ退避しながらruntimeを実行するentrypoint、Lambdaのruntimeがhandlerを実行する時にそれを復元するshimで構成されています。
すでにECSで運用しているコンテナイメージがあるなら、上記のような動きをするファイルを仕込み、Lambdaの設定でentrypointを変更すればECSとLambdaで共用できるイメージが出来上がります。どうぞお試しあれ。