概要
ローカル開発環境のdockerでS3を起動してJavaからアクセスする。
MinIO https://min.io/ を使用する。dockerhubは https://hub.docker.com/r/minio/minio
サンプルコード
docker run
とりあえず最低限の動作確認を行うためのコマンド。
docker run -p 9000:9000 -p 9001:9001 minio/minio:RELEASE.2024-12-18T13-15-44Z.fips server /data --console-address ":9001"
実行時のログ例は以下の通り。
INFO: Formatting 1st pool, 1 set(s), 1 drives per set. INFO: WARNING: Host local has more than 0 drives of set. A host failure will result in data becoming unavailable. MinIO Object Storage Server Copyright: 2015-2025 MinIO, Inc. License: GNU AGPLv3 - https://www.gnu.org/licenses/agpl-3.0.html Version: RELEASE.2024-12-18T13-15-44Z (go1.23.4 X:boringcrypto linux/amd64) API: http://172.17.0.2:9000 http://127.0.0.1:9000 WebUI: http://172.17.0.2:9001 http://127.0.0.1:9001 Docs: https://docs.min.io WARN: Detected default credentials 'minioadmin:minioadmin', we recommend that you change these values with 'MINIO_ROOT_USER' and 'MINIO_ROOT_PASSWORD' environment variables
- https://hub.docker.com/r/minio/minio - imageのversionは左記から適宜参照。
--console-address ":9001"によりWeb UIのportがこれになる。URLはログにある通りhttp://127.0.0.1:9001- Web UIのデフォルトのcredentialはログにある通り
minioadmin:minioadminで基本的には変更するものだろう。
Web UI
http://localhost:9001/ でWeb UIにアクセスして適当なオブジェクトを作成しておく。

Access Keys -> Create access key

適当なAccess Keyを作成。

適当なbucketを作成。ここではsample1という名前にしている。

Object Browser -> さっき作ったsample1のBucket -> Uploadで適当なファイルをUploadする。

Java
https://mvnrepository.com/artifact/software.amazon.awssdk/s3 の依存性を追加。
implementation 'software.amazon.awssdk:s3:2.29.50'
さっき作ったbucketにアクセスしてオブジェクトを取得する。
import java.net.URI; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.AwsCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; public class S3SampleMain { public static void main(String[] args) { AwsCredentials credentials = AwsBasicCredentials.create("xxx", "xxx"); S3Client client = S3Client.builder() .region(Region.US_EAST_1) .credentialsProvider(StaticCredentialsProvider.create(credentials)) .endpointOverride(URI.create("http://localhost:9000")) .forcePathStyle(true) .build(); GetObjectRequest request = GetObjectRequest .builder() .key("hogehoge.txt") .bucket("sample1") .build(); ResponseBytes<GetObjectResponse> response = client.getObjectAsBytes(request); String message = response.asUtf8String(); System.out.println(message); } }
credentialsにはWeb UIで作成したAccesss Keyを指定する。endpointOverrideにはdocker run時のログAPI: (略) http://127.0.0.1:9000に従ったURLを指定する。forcePathStyle(true)はローカルで試す分には必要。GetObjectRequestにあらかじめ作成しておいたオブジェクトを指定する。
ハマったところ
region(Region.US_EAST_1)は必要
未指定だと以下のような例外になる。
Exception in thread "main" software.amazon.awssdk.core.exception.SdkClientException: Unable to load region from any of the providers in the chain software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain@732c2a62: [software.amazon.awssdk.regions.providers.SystemSettingsRegionProvider@1ff4931d: Unable to load region from system settings. Region must be specified either via environment variable (AWS_REGION) or system property (aws.region)., software.amazon.awssdk.regions.providers.AwsProfileRegionProvider@510f3d34: No region provided in profile: default, software.amazon.awssdk.regions.providers.InstanceProfileRegionProvider@1ba9117e: Unable to contact EC2 metadata service.]
Received an UnknownHostException when attempting to interact with a service.
https://dev.classmethod.jp/articles/access-minio-using-aws-sdk-for-go/ にある通り S3Client#forcePathStyle(true) が必要となる。
Exception in thread "main" software.amazon.awssdk.core.exception.SdkClientException: Received an UnknownHostException when attempting to interact with a service. See cause for the exact endpoint that is failing to resolve. If this is happening on an endpoint that previously worked, there may be a network connectivity issue or your DNS cache could be storing endpoints for too long.
...
at org.example.app.S3SampleMain.main(S3SampleMain.java:47)
Caused by: software.amazon.awssdk.core.exception.SdkClientException: Unable to execute HTTP request: sample0001.localhost
...
Suppressed: software.amazon.awssdk.core.exception.SdkClientException: Request attempt 1 failure: Unable to execute HTTP request: ���̂悤�ȃz�X�g�͕s���ł��B (sample0001.localhost)
Suppressed: software.amazon.awssdk.core.exception.SdkClientException: Request attempt 2 failure: Unable to execute HTTP request: sample0001.localhost
Suppressed: software.amazon.awssdk.core.exception.SdkClientException: Request attempt 3 failure: Unable to execute HTTP request: sample0001.localhost
Caused by: java.net.UnknownHostException: sample0001.localhost
...