## 事象 こんな感じでエラーになる。 ```mermaid flowchart LR PC --OK---> samlocal[SAM Local] PC --OK---> LocalStack samlocal -.-> |NG| LocalStack ``` エラーメッセージ。 ``` operation error S3: ListObjectsV2, exceeded maximum number of attempts, 3, https response error StatusCode: 0, RequestID: , HostID: , request send failed, Get "http://minerva.localhost:4566/?list-type=2": dial tcp: lookup minerva.localhost on 192.168.65.5:53: no such host ``` `minerva`がバケット名。 ## 原因 原因は2つある。 ### [[LocalStack]]の[[S3]]が[[サブドメイン]]をサポートしていない つまり、`minerva.localhost:4566`を解釈できない。 [Support for s3 bucket subdomains · Issue \#2631 · localstack/localstack](https://github.com/localstack/localstack/issues/2631) ### ネットワークが異なる [[SAM Local]]のコンテナから[[LocalStack]]コンテナのネットワークが見えていないから。 ## 対策 ### カスタムResolverのエンドポイントを切り替える `s3.localhost.localstack.cloud`の意味は別途確認 #todo ```go func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { // awsEndpoint := "http://localhost:4566" awsEndpoint := "http://s3.localhost.localstack.cloud:4566" customResolver := aws.EndpointResolverFunc(func(service, region string) (aws.Endpoint, error) { if awsEndpoint != "" { return aws.Endpoint{ URL: awsEndpoint, SigningRegion: "ap-northeast-1", }, nil } return aws.Endpoint{}, &aws.EndpointNotFoundError{} }) // 中略 } ``` ### サブドメインを認識させる `networks.default.aliases`にデバッグで使用するバケットのサブドメインを一通りしておく。今回は`minerva`バケットを作成したため、以下のようにする。 `docker-compose.yml` ```yaml version: '3' services: s3: image: localstack/localstack:latest hostname: s3 ports: - "4566:4566" networks: default: aliases: # これを追加 - s3.localhost.localstack.cloud - s3-website.localhost.localstack.cloud - minerva.s3.localhost.localstack.cloud - minerva.s3-website.localhost.localstack.cloud environment: SERVICES: s3 DEFAULT_REGION: ap-northeast-1 DEBUG: "1" expose: - "4566" ``` これで[[LocalStack]]コンテナが`minerva.localhost:4566`を解釈できるようになる。[[LocalStackでS3]]も参考に。 ### ネットワークについて [[SAM Local]]のコンテナ立ち上げ時に、[[LocalStack]]コンテナが利用しているネットワークを指定してあげればいい。 ```console $ docker network ls NETWORK ID NAME DRIVER SCOPE 58ac9d8ac820 bridge bridge local 313fd89d94f1 host host local 21c3b22060e6 none null local df6fe0d5afeb sam-app_default bridge local ``` 今回は[^1]`sam-app_default`の`NETWORK ID`が欲しいので以下コマンドで取得できる。 ```console $ docker network ls -q --filter 'name=sam-app_default' df6fe0d5afeb ``` これを`sam local`コマンドの`--docker-network`に渡してあげる。 ```console sam local start-api --docker-network $(docker network ls -q --filter 'name=sam-app_default') ``` [^1]: NAMEは環境や設定によって変わる