DevContainer内でAWS SAMのLambdaのローカル実行機能を使いたいときの注意点
サーバレス開発でもDevContainerを使いたい
VSCodeのRemote Container機能(DevContainer)を使うと、コンテナ内で開発ができ、開発環境をチーム内で統一するのが容易など何かと嬉しいです。が、AWS SAMでLambdaをローカル実行してDBに接続しようとすると少し厄介な事象にハマります。
この記事はそれをどうにかするのが目的です。
何が問題になるか
AWS SAMでLambda & API Gatewayのエミュレートを行う場合、AWS公式のLambdaイメージから、実行用のDockerコンテナを作成し実行されます。
そのため、DevContainerを用いて、この操作を行いたい場合、Dockerコンテナの中にDockerコンテナが入り込む形になります。
この際、別にローカルで作ったDBへのアクセスを行おうとすると、ネットワーク周りがなかなかうまく行かないといったことが起こります。
事前知識
Dockerコンテナの中にDockerコンテナが入り込む形には2種類存在します。
- docker-in-docker: ホストで動いているDockerの中で、別のDockerが走る。DIDと略されることも。
- 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