使用AWS Localstack S3 筆記

對於常開發與使用AWS的開發者來說,要實作一些整合測試時通常會比較麻煩點,尤其是通常會需要在有網路的環境下做開發與測試。

Github上的這個Localstack 專案,就是為了解決這個痛點而存在的,它幫助AWS開發者搭建本地端的AWS 服務,舉例來說,我們可以透過Localstack在本地端搭建一個S3讓我們所開發的應用程式去連接。

目前Localstack支援的AWS 服務可以在他們的github頁面上找到,常見的API Gateway, DynamoDB, Lambda and S3都可以使用,如果是使用他們的付費方案, 則有支援更多的AWS 服務。

搭建Localstack S3

目前剛好有用到S3,所以記錄一下透過下面docker-compose.yaml來啟用Localstack的方式:

version: "3.3"
 services:
   localstack:
     image: localstack/localstack
     network_mode: bridge
     ports:
       - "4566:4566"
       - "4571:4571"
     environment:
       - SERVICES=s3
       - EDGE_PORT=4566
       - AWS_DEFAULT_REGION=us-east-1
     volumes:
       - "${TMPDIR:-/tmp/localstack}:/tmp/localstack"
       - "/var/run/docker.sock:/var/run/docker.sock"

NOTE:

  • 這邊的SERVICES是可以指定多個服務的,例如SERVICE=s3,lambda
  • EDGE_PORT目前預設也是4566,主要是用來在本地端服務的port number。
  • 更多詳細的docker-compose.yaml 範例可以參考官方的這個例子

使用AWS CLI 連接 Localstack S3

在透過上面提到的方式搭建好本地端的S3以後,其實就可以直接用AWS CLI來去連到我們剛架好的S3了;唯一要注意的是,我們在使用cli 時必須指定對應的endpoint-url到我們剛架好的本地端url。

透過docker aws cli 連接Localstack s3

docker exec -t -e AWS_ACCESS_KEY_ID=1 -e AWS_SECRET_ACCESS_KEY=abc container_localstack_1 aws --endpoint-url=http://127.0.0.1:4566 s3 mb s3://my_bucket

NOTE:
透過AWS Cli連接 Localstack時,必須指定key_idkey,要不然會報錯

透過AWS Go SDK

如果要透過Go AWS SDK 去連接Localstack S3的話,會有個額外要設定的AWS.Config欄位,其具體的範例程式碼為:

awsCfg := &aws.Config{
   Credentials: credentials.NewStaticCredentials(awsKeyId, awsKeySecret, ""),
   Region:      aws.String(region),
}

if customEndpoint != "" {
   awsCfg.Endpoint = aws.String("http://localhost:4566")
   awsCfg.S3ForcePathStyle = aws.Bool(true)
}

在這邊,設定 S3ForcePathStyle=true 主要是為了讓Go SDK與連接S3的時候會把bucket 的資訊透過path的方式去代入到resource的uri中。

舉例來說,如果我們有個bucket=my_bucket,而我們在這個bucket裡面的一個測試檔案test.txt的完整uri為是http://localhost:4566/my_bucket/test.txt;有了這樣的設定,才會讓我們使用Go AWS SDK時,可以正確的存取Localstack S3上的檔案。

如果我們使用S3ForcePathStyle=false的話,則同個檔案, Go AWS SDK會使用這個uri: http://my_bucket.localhost:4566/test.txt 去存取Localstack上的檔案;顯然地,這個uri是有問題的,因為Localstack S3 是在listen http://localhost:4566,而不是http://my_bucket.localhost:4566這個子網域。

更多詳細的說明可以參考官方的這個issue:https://github.com/aws/aws-sdk-go/issues/2743

Reference: