🚀

M1 Mac で Rust 製 Lambda + SAM をどうにかして使えるようにした話

2024/05/04に公開1

きっかけ

新しいもの好きである私は、今年 Rust を始めました。 The Rust Programming Language は初めて高級言語を触る人にもわかりやすく、とても良かったです。

仕事で新たにチームにジョインした新卒メンバーに AWS について講義を行いましたが、久々にサーバーレスアーキテクチャをフル活用したアプリケーションを作りたくなり、せっかくならば最近学んだ Rust を使ってみようと思ったのがきっかけです。

やってみた

もともと他の開発で AWS CLI と SAM や Docker は入っていたので、 公式ドキュメント をベースに簡単なチュートリアルを進めようと思っていました。正直、実装も発生しないため 30 分程度あれば終わるだろうと思って始めていましたが、m1 Mac を使っていたがゆえに、思わぬ問題にぶつかりました。

問題

sam buildsam deploy --guided を使い、 Lambda が無事にデプロイされましたが CLI の Output に表示されたエンドポイントへアクセスするとなんとインターナルサーバーエラーが返されてしまいました。エラーを見る限り、要求している GLIBC のバージョンが合わないようでした。

/var/task/bootstrap: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by /var/task/bootstrap)

Go でも前に似たようなエラーに遭遇しており、このときは GOOS=linux GOARCH=amd64 を使ってビルドすることで解決したものの、 cargo にはこのようなオプションが自分で調べる限りは見つけられず、かなり困りました。

このような問題は割と前から認知されていたようで、 awslabs/aws-lambda-rust-runtime#17 でも議論されていました。

解決策

The alternative is to build on a container that matches the lambda runtime.

結局上で上げた issue で解決するのがワークアラウンドで、devcontainer で解決しました。(厳密には VS Code の拡張機能の方を使っています)

.devcontainer/devcontainer.json
{
  "name": "Rust",
  "image": "mcr.microsoft.com/devcontainers/rust:1-1-bullseye",
  "mounts": [
    {
      "source": "${localEnv:HOME}/.aws",
      "target": "/home/vscode/.aws",
      "type": "bind"
    }
  ],
  "features": {
    "ghcr.io/audacioustux/devcontainers/aws-sam-cli:1": {},
    "ghcr.io/devcontainers/features/nix:1": {
      "packages": "nixpkgs.cargo-lambda",
      "useAttributePath": true
    },
    "ghcr.io/devcontainers/features/aws-cli:1": {},
    "ghcr.io/devcontainers/features/docker-in-docker:2": {}
  }
}

Rust をベースイメージとし、 SAM CLI、 AWS CLI、 Docker in Docker と Nix による cargo-lambda を使うことで、環境を構築しました。また、 .aws ディレクトリをマウントすることで、 AWS の認証情報を共有しました。

これによって、一度この構成でビルドしたイメージをベースに必要なアプリケーションがプリインストールされた状態で開発ができるようになりました。

おわり

PS: もっといい方法があれば教えてください 🙇‍♂️

GitHubで編集を提案

Discussion