GoとSAMの開発環境をコンテナで構築するメモ
devcontainer.json
に以下追記
︙
"features": {
"ghcr.io/devcontainers/features/aws-cli:1": {},
"ghcr.io/customink/codespaces-features/sam-cli:1": {}
}
︙
AWS CLIとSAM CLIが入る
featuresの一覧は以下に記載あり。必要に応じて追記する。
vscodeでdevcontainer.jsonを生成する場合は、GUIで選択できて便利。
ベースをgoの開発用imageにしていたが、dind(dood)のimageにしたほうがいいかも。
(開発コンテナ内のsamでエミュレートする際にコンテナが必要なため)
嘘。featuresにありました。
というわけでこう
︙
"features": {
"ghcr.io/devcontainers/features/aws-cli:1": {},
"ghcr.io/customink/codespaces-features/sam-cli:1": {},
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
}
︙
コンテナのdynamodb-local(ホストOS上のコンテナ)を使いたかったが、dind(開発コンテナ上のコンテナ)では接続できないかも?
doodに変更してみる。
doodではsamを実行しているコンテナに接続する際にタイムアウトしてしまった。
$ sam local invoke
Invoking main (go1.x)
Local image is up-to-date
Using local image: public.ecr.aws/lambda/go:1-rapid-x86_64.
Mounting /workspaces/HCW-SS-Viewer/.aws-sam/build/xxxx as /var/task:ro,delegated, inside runtime container
Timed out while attempting to establish a connection to the container. You can increase this timeout by setting the SAM_CLI_CONTAINER_CONNECTION_TIMEOUT environment variable. The current timeout is 20.0
(seconds).
同じ事象(?)が起きているが、Macでは実行できている。(host.docker.internalによる)
linuxでhost.docker.internalを使ってホストのサービスにアクセスしている。(Docker Engine 20.10.0以降)
開発コンテナからsam local invoke するときにホストOSのIPアドレスを指定してやればいい?
とりあえず開発コンテナでhost.docker.internalを使えるようにしてみる。
手元でいじっている環境はdocker composeの開発コンテナなので、docker-compose.ymlに追記した。
version: '3'
services:
api:
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ..:/workspaces:cached
command: /bin/sh -c "while sleep 1000; do :; done"
dokcerコンテナ単体の開発コンテナであれば、devcontainer.jsonに追記?
# docker-compose.yml無いとき
{
"runArgs": ["--add-host=host.docker.internal:host-gateway"]
}
開発コンテナをリビルドして、/etc/hostsを確認してみる。
$ cat /etc/hosts | grep internal
172.17.0.1 host.docker.internal
sam local invoke
してみる。
状況変わらず。
$ sam local invoke
Invoking main (go1.x)
Local image is up-to-date
Using local image: public.ecr.aws/lambda/go:1-rapid-x86_64.
Mounting /workspaces/xxxx/.aws-sam/build/xxxx as /var/task:ro,delegated, inside runtime container
Timed out while attempting to establish a connection to the container. You can increase this timeout by setting the SAM_CLI_CONTAINER_CONNECTION_TIMEOUT environment variable. The current timeout is 20.0 (seconds).
--container-host
オプションをつけてhost.docker.internalを指定してみる。
状況変わらず。
$ sam local invoke --container-host host.docker.internal
Invoking main (go1.x)
Local image is up-to-date
Using local image: public.ecr.aws/lambda/go:1-rapid-x86_64.
Mounting /workspaces/xxxx/.aws-sam/build/xxxx as /var/task:ro,delegated, inside runtime container
Timed out while attempting to establish a connection to the container. You can increase this timeout by setting the SAM_CLI_CONTAINER_CONNECTION_TIMEOUT environment variable. The current timeout is 20.0 (seconds).
--container-host-interface
オプションもつけてみる。
お?
sam local invoke --container-host host.docker.internal --container-host-interface host.docker.internal
Invoking main (go1.x)
Local image is up-to-date
Using local image: public.ecr.aws/lambda/go:1-rapid-x86_64.
Mounting /workspaces/xxxx/.aws-sam/build/xxxx as /var/task:ro,delegated, inside runtime container
START RequestId: 3ae54bfb-f432-4c9d-a9ce-ce95bc8611db Version: $LATEST
fork/exec /var/task/main: no such file or directory: PathError
null
END RequestId: 3ae54bfb-f432-4c9d-a9ce-ce95bc8611db
REPORT RequestId: 3ae54bfb-f432-4c9d-a9ce-ce95bc8611db Init Duration: 0.05 ms Duration: 6.21 ms Billed Duration: 7 ms Memory Size: 512 MB Max Memory Used: 512 MB
{"errorMessage":"fork/exec /var/task/main: no such file or directory","errorType":"PathError"}
ホストとコンテナ内のパスが一致していないとうまく動かないという話を見た。(どこで見たのか忘れてしまった...)
以下の通りdocker-compose.ymlを変更してみる。
version: '3'
services:
api:
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- .:/$PWD:cached
command: /bin/sh -c "while sleep 1000; do :; done"
samでLambdaを実行できた雰囲気を感じる
sam local invoke --container-host host.docker.internal --container-host-interface host.docker.internal
SAM CLI now collects telemetry to better understand customer needs.
You can OPT OUT and disable telemetry collection by setting the
environment variable SAM_CLI_TELEMETRY=0 in your shell.
Thanks for your help!
Learn More: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-telemetry.html
Invoking main (go1.x)
Local image is out of date and will be updated to the latest runtime. To skip this, pass in the parameter --skip-pull-image
Building image....................................................
Using local image: public.ecr.aws/lambda/go:1-rapid-x86_64.
Mounting /home/sut103/dev/xxxx/.aws-sam/build/xxxx as /var/task:ro,delegated, inside runtime container
START RequestId: dc8f8445-7eae-4ce6-acf6-c735be684436 Version: $LATEST
2023/07/20 03:44:10 2023-07-20 03:44:10.070372981 +0000 UTC m=+0.238315686 getScreenshots(): operation error DynamoDB: Scan, https response error StatusCode: 400, RequestID: LRLVKH70JID3GTA6KCBIBOTPQRVV4KQNSO5AEMVJF66Q9ASUAAJG, api error UnrecognizedClientException: The security token included in the request is invalid.
{"statusCode":500,"headers":null,"multiValueHeaders":{"Content-Type":["application/json; charset=UTF-8"]},"body":"{\"message\":\"Internal Server Error\"}\n"}END RequestId: dc8f8445-7eae-4ce6-acf6-c735be684436
REPORT RequestId: dc8f8445-7eae-4ce6-acf6-c735be684436 Init Duration: 0.28 ms Duration: 264.90 ms Billed Duration: 265 ms Memory Size: 512 MB Max Memory Used: 512 MB
SAM CLI update available (1.92.0); (1.90.0 installed)
To download: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html
エラーの出ている部分はDynamoDB-Localとの接続。(環境変数を入れてない)
接続情報を適切に入力しつつ、DynamoDB-Localと同じDocker networkにsam コンテナを接続してやればつながる。
docker networkを合わせないで、host.docker.internalを使ってdynamodbに繋げられる方が便利そうだなぁ...。今のところ不明
その他拡張機能や設定をカスタマイズしたい場合は以下に記載。
︙
"customizations": {
// Configure properties specific to VS Code.
"vscode": {
// Set *default* container specific settings.json values on container create.
"settings": {},
"extensions": [],
}
}
︙
sam build
-> sam local invoke
すると以下の通りエラー
$ sam local invoke
Invoking main (go1.x)
Local image is up-to-date
Using local image: public.ecr.aws/lambda/go:1-rapid-x86_64.
Mounting /workspaces/xxx/.aws-sam/build/xxx as /var/task:ro,delegated, inside runtime container
START RequestId: 6f3e1509-3527-4d06-83a9-13e92304196d Version: $LATEST
/var/task/main: /lib64/libc.so.6: version `GLIBC_2.32' not found (required by /var/task/main)
/var/task/main: /lib64/libc.so.6: version `GLIBC_2.34' not found (required by /var/task/main)
2023/07/12 08:34:25 exit status 1
12 Jul 2023 08:34:25,127 [ERROR] (rapid) Init failed error=Runtime exited with error: exit status 1 InvokeID=
/var/task/main: /lib64/libc.so.6: version `GLIBC_2.32' not found (required by /var/task/main)
/var/task/main: /lib64/libc.so.6: version `GLIBC_2.34' not found (required by /var/task/main)
2023/07/12 08:34:25 exit status 1
END RequestId: 080c16ee-0b21-4eb7-b582-a298593d3fb7
REPORT RequestId: 080c16ee-0b21-4eb7-b582-a298593d3fb7 Init Duration: 0.05 ms Duration: 11.52 ms Billed Duration: 12 ms Memory Size: 512 MB Max Memory Used: 512 MB
GoをLambdaにアップロードする際は公式ドキュメントの記載に従って以下の通り環境変数を指定してビルドするが、おそらくsam buildの中ではそうなっていない。
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o main main.go
ビルド環境と実行環境でCライブラリのバージョンが異なるとうまく動作しないらしい。
本来は上記の環境変数CGO_ENABLED=0
で無効化して差異が出ないようにしている。
というわけでsam build
する前に開発コンテナ上に環境変数を設定してあげればok
export CGO_ENABLED=0
開発コンテナの設定として書いてしまって良さそう。
︙
"containerEnv": {
"CGO_ENABLED":"0"
}
︙