## 事象
こんな感じでエラーになる。
```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は環境や設定によって変わる