👻

DevContainer内でAWS SAMのLambdaのローカル実行機能を使いたいときの注意点

2022/10/05に公開

サーバレス開発でもDevContainerを使いたい

VSCodeのRemote Container機能(DevContainer)を使うと、コンテナ内で開発ができ、開発環境をチーム内で統一するのが容易など何かと嬉しいです。が、AWS SAMでLambdaをローカル実行してDBに接続しようとすると少し厄介な事象にハマります。
この記事はそれをどうにかするのが目的です。

何が問題になるか

AWS SAMでLambda & API Gatewayのエミュレートを行う場合、AWS公式のLambdaイメージから、実行用のDockerコンテナを作成し実行されます。
そのため、DevContainerを用いて、この操作を行いたい場合、Dockerコンテナの中にDockerコンテナが入り込む形になります。
この際、別にローカルで作ったDBへのアクセスを行おうとすると、ネットワーク周りがなかなかうまく行かないといったことが起こります。

事前知識

Dockerコンテナの中にDockerコンテナが入り込む形には2種類存在します。

  1. docker-in-docker: ホストで動いているDockerの中で、別のDockerが走る。DIDと略されることも。
  2. docker-from-docker: ホストのDockerとdockerデーモンを共有。docker-outside-of-docker(dood)とも呼ばれる。

参考: Dockerコンテナ内からDockerを使うことについて

解決方法

1. Docker-from-docker構成を取る

devcontainer.jsonに以下を追加(こちらは実験的機能を使った実装方法にはなります)

"features": {
    "docker-from-docker": {
        "version": "latest"
    }
}

2. Docker内でオプションが効かないエラーに対応

--docker-volume-basedirオプションがDocker内では効かないので、devcontainer.jsonに以下を追加することで、やや無理やりですが対処可能です。
(参考: 【Docker】Step Functions localとSAM LocalをDocker内で使用してみる

working_dir: $PWD
volumes:
      - $PWD:$PWD

実行

いくつかネットワーク系のオプションを入れつつ実行すれば動くはずです。

$ sam local start-api --host 0.0.0.0 --container-host host.docker.internal

DBに繋ぐ場合は--docker-network (DBと共有するnetwork名)が必要になるかもしれないです(記憶が曖昧)

結論

良いサーバレス開発ライフを〜

Discussion