AWS SDK for Goからminioへのアクセスでハマったこと

AWS SDK for Goを使ってminioにアクセスするとエラーになってしまいました。エラーの内容と解消方法を紹介しています。
2018.08.31

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

先日の投稿 で紹介したminioを使ってみたところ、AWS SDK for Goでアクセスするとエラーになってしまいました。今回は備忘のためハマった内容と解消方法をまとめてみます。

検証環境

  • Docker: 18.06.0-ce
  • minio: 2018-08-02T23:11:36Z
  • Go: 1.10.3
  • AWS SDK for Go: v1.15.25

ハマったこと

以下のソースコードでminioのオブジェクトを列挙しようとしたところエラーが発生しました。簡略化のためエラー発生時は panic で中断するようにしています。

main.go

package main

import (
	"fmt"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
)

func newS3() (*s3.S3, error) {
	s, err := session.NewSession()
	if err != nil {
		return nil, err
	}

	ak := "MINIO_ACCESS_KEY"
	sk := "MINIO_SECRET_KEY"
	cfg := aws.Config{
		Credentials: credentials.NewStaticCredentials(ak, sk, ""),
		Region:      aws.String("ap-northeast-1"),
		Endpoint:    aws.String("http://127.0.0.1:9000"),
	}
	return s3.New(s, &cfg), nil
}

func main() {
	c, err := newS3()
	if err != nil {
		panic(err)
	}

	bucket := "minio-bucket"
	var token *string
	for complete := false; !complete; {
		in := s3.ListObjectsV2Input{Bucket: &bucket, ContinuationToken: token}
		out, err := c.ListObjectsV2(&in)
		if err != nil {
			panic(err)
		}

		for i, o := range out.Contents {
			fmt.Printf("[%d] : %s\n", i, *o.Key)
		}

		complete = out.IsTruncated != nil && !*out.IsTruncated
		token = out.NextContinuationToken
	}
}

この状態で実行するとエラーが発生しました。

$ go run main.go
panic: RequestError: send request failed
caused by: Get http://minio-bucket.127.0.0.1:9000/?list-type=2: dial tcp: lookup minio-bucket.127.0.0.1: no such host

goroutine 1 [running]:
main.main()
    /Users/yoshihitoh/go/src/use-minio/main.go:40 +0x317
exit status 2

http://{{ バケット名 }}.{{ エンドポイント }}/ の形式でURLを組み立てるようで、ローカル環境だとうまく動きません。

解消方法

どうしたものかと調べてみると、minioのcookbookにズバリな解決方法がのっていました。

aws.Config#S3ForcePathStyle の設定が必要なようです。構造体の初期化を以下の内容に書き換えます。

    cfg := aws.Config{
        Credentials:      credentials.NewStaticCredentials(ak, sk, ""),
        Region:           aws.String("ap-northeast-1"),
        Endpoint:         aws.String("http://127.0.0.1:9000"),
        S3ForcePathStyle: aws.Bool(true), // NOTE: この指定を追加
    }

再度実行してみます。

$ go run main.go
[0] : hello-minio.txt

今度はうまく動きましたね!

おわりに

見慣れないエラーで解消できるんかなーと不安でしたが、cookbookのおかげですんなり解消できました。他の言語のAWS SDK利用方法や、aws-cli、s3cmdの利用方法も記載されています。情報が充実していて素晴らしいですね。