MinIOドキュメントに aws-sdk-go
を使用したサンプルはあるのですが、 aws-sdk-go-v2
のものはないため備忘録を残しておきます。
MinIO
オープンソースのオブジェクトストレージです。 S3互換のため、S3 API経由で接続することができます。
MinIO の立ち上げ
Docker imageがあるのでこれを利用してserver用コンテナを立ち上げます。
$ docker container run -d --name minio -p 9000:9000 -p 9001:9001 minio/minio server /data --console-address ":9001"
MinIOには管理コンソールがあるので、アプリケーション用だけでなく管理コンソール用portも指定&forwardingします。
管理コンソールのportは --console-address
で指定できます。指定しないとephemeral portが毎回ランダムに割り当てられてしまうので、明示的に指定したほうが楽です。
管理画面はブラウザ上でアクセスでき、credentialは↓で確認できます。credentialは環境変数 MINIO_ROOT_USER
MINIO_ROOT_PASSWORD
で設定できますが、特に指定がなければ minioadmin:minioadmin
になります。
$ docker logs minio API: http://172.17.0.2:9000 http://127.0.0.1:9000 Console: http://172.17.0.2:9001 http://127.0.0.1:9001 Documentation: https://docs.min.io WARNING: Detected default credentials 'minioadmin:minioadmin', we recommend that you change these values with 'MINIO_ROOT_USER' and 'MINIO_ROOT_PASSWORD' environment variables
aws-sdk-go-v2でMinIOを叩く
import ( "bytes" "context" "log" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/service/s3" ) func main() { ctx := context.Background() accessKey := "<access-key>" secretKey := "<secret-key>" cred := credentials.NewStaticCredentialsProvider(accessKey, secretKey, "") endpoint := aws.EndpointResolverFunc(func(service, region string) (aws.Endpoint, error) { return aws.Endpoint{ URL: "http://localhost:9000", }, nil }) cfg, err := config.LoadDefaultConfig(ctx, config.WithCredentialsProvider(cred), config.WithEndpointResolver(endpoint)) if err != nil { log.Fatalln(err) } // change object address style client := s3.NewFromConfig(cfg, func(options *s3.Options) { options.UsePathStyle = true }) // get buckets lbo, err := client.ListBuckets(ctx, nil) if err != nil { log.Fatalln(err) } buckets := make(map[string]struct{}, len(lbo.Buckets)) for _, b := range lbo.Buckets { buckets[*b.Name] = struct{}{} } // create 'develop' bucket if not exist bucketName := "develop" if _, ok := buckets[bucketName]; !ok { _, err = client.CreateBucket(ctx, &s3.CreateBucketInput{ Bucket: &bucketName, }) if err != nil { log.Fatalln(err) } } // put object _, err = client.PutObject(ctx, &s3.PutObjectInput{ Bucket: &bucketName, Key: aws.String("hogehoge"), Body: bytes.NewReader([]byte("Hello, MinIO!")), }) if err != nil { log.Fatalln(err) } }
aws-sdk-go-v2からMinIOを叩く際に考慮する点が1つあります。
オブジェクトアドレスをpath styleにする
S3にはpath style と virtual-hosted styleのアドレスがあります。path styleではバケット名がpathに含まれていましたが、virtual-hosted styleではURLドメインに含まれるようになります。
- path style:
https://s3-us-east-1.amazonaws.com/bucket-name/images/obj.jpeg
- virtual-hosted style:
https://bucket-name.s3.amazonaws.com/images/obj.jpeg
AWS S3だと現時点でvirtual-hosted style のアドレスが使用されていますが、MinIOは対応していないのでpath styleでアクセスする必要があります。
path styleへの変更は s3.NewFromConfig
に options.UsePathStyle=true
書き換えを行う func(options *s3.Options)
を渡します。
client := s3.NewFromConfig(cfg, func(options *s3.Options) { options.UsePathStyle = true })
管理コンソール上でuploadされたオブジェクトを確認できます。