對於常開發與使用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_id
與key
,要不然會報錯
透過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