事象
SAM コマンドで実行したLambdaから、 LocalStack で立てたS3にアクセスできない
TL;DR
macの場合、Lambdaから接続するhostを localstack
ではなく host.docker.internal
にする
https://github.com/localstack/localstack/issues/878
実装
version: "3.8"
services:
localstack:
container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}"
image: localstack/localstack
network_mode: bridge
ports:
- "127.0.0.1:53:53"
- "127.0.0.1:53:53/udp"
- "127.0.0.1:443:443"
- "127.0.0.1:4566:4566"
- "127.0.0.1:4571:4571"
environment:
- SERVICES=s3
- DEBUG=${DEBUG- }
- DATA_DIR=/tmp/localstack/data
- DOCKER_HOST=unix:///var/run/docker.sock
- DEFAULT_REGION=ap-northeast-1
volumes:
- "./work:/tmp/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
package main
import (
"context"
"io/ioutil"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
func handler(event events.CloudWatchEvent) (string, error) {
cfg, _ := config.LoadDefaultConfig(context.TODO(),
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider("dummy", "dummy", "dummy")),
)
// localstack S3のURL
er := awsS3.EndpointResolverFromURL("http://host.docker.internal:4566")
client := s3.NewFromConfig(cfg,
s3.WithEndpointResolver(er),
// localstack S3の場合、virtual hostでのアクセスができないためpath styleを使う
func(o *s3.Options) {
o.UsePathStyle = true
},
)
input := &s3.GetObjectInput{
Bucket: aws.String("sample-bucket"),
Key: aws.String("path/to/file"),
}
output, err := client.GetObject(context.TODO(), input)
if err != nil {
return "", err
}
defer output.Body.Close()
b, err := ioutil.ReadAll(output.Body)
if err != nil {
return "", err
}
return string(b), nil
}
func main() {
lambda.Start(handler)
}
参考
AWS SAM CLI と localstack を利用して Lambda をローカル実行してみよう AWS SAM Local と LocalStack を使って ローカルでAWS Lambdaのコードを動かす | DevelopersIO