JavaからMinioを使用するサンプルコード
最近、Amazon S3に依存するアプリケーションの自動テストに、S3互換ストレージであるMinioを使うようにしています。ここで、Java(SpringBoot)からAWS SDK for Javaを使用してMinioにアクセスするサンプルコードを作成します。
Minioとは
S3クローンの一つで、S3互換なのでAWS SDKなどでAmazon S3と同様にアクセスすることができます。手軽にS3互換ストレージを使用することができて便利。
前提条件
- Docker
- 筆者は、Windows 10にDocker ToolboxをインストールしてDocker環境を構築しています。
- Dockerが動作すれば、他の環境でも問題ないはず。
$ docker version
docker version
Client:
Version: 1.12.5
API version: 1.24
Go version: go1.6.4
Git commit: 7392c3b
Built: Fri Dec 16 06:14:34 2016
OS/Arch: linux/amd64
Server:
Version: 1.12.5
API version: 1.24
Go version: go1.6.4
Git commit: 7392c3b
Built: Fri Dec 16 06:14:34 2016
OS/Arch: linux/amd64
- Java SDK 8
# java -version
openjdk version "1.8.0_121"
OpenJDK Runtime Environment (IcedTea 3.3.0) (Alpine 8.121.13-r0)
OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)
- Apache Maven 3
# mvn -version
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-10T16:41:47+00:00)
Maven home: /usr/share/java/maven-3
Java version: 1.8.0_121, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-1.8-openjdk/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.4.59-boot2docker", arch: "amd64", family: "unix"
- Minio
- いくつかの使用方法がありますが、ここではDockerコンテナとして動作させます。
- Minio側のバグにより、latestではなくedgeを使用します。
手順
MinioをDockerコンテナとして動作させて、SpringBootアプリケーションからアクセスする手順を説明します。作成済みのサンプルコードは u6k/sample-minio にあります。
Minioコンテナを動作させてみる
Minio Docsの「Docker Container」を参考に動作させてみます。
$ docker run \
-d \
--name s3 \
-p 9000:9000 \
minio/minio:edge server /export
正常に起動すると、以下のようにログ出力されます。
$ docker logs s3
Created minio configuration file successfully at /root/.minio
Endpoint: http://172.17.0.2:9000 http://127.0.0.1:9000
AccessKey: xxxxxxxxxxxxxxxxxxxx
SecretKey: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Region: us-east-1
SQS ARNs: <none>
Browser Access:
http://172.17.0.2:9000 http://127.0.0.1:9000
Command-line Access: https://docs.minio.io/docs/minio-client-quickstart-guide
$ mc config host add myminio http://172.17.0.2:9000 C05JGTT0UWNXW25Y4IHN zg1JZrFIAWM0dZmXkPF93ZOXXf6Vj3F/QgycmLZE
Object API (Amazon S3 compatible):
Go: https://docs.minio.io/docs/golang-client-quickstart-guide
Java: https://docs.minio.io/docs/java-client-quickstart-guide
Python: https://docs.minio.io/docs/python-client-quickstart-guide
JavaScript: https://docs.minio.io/docs/javascript-client-quickstart-guide
Drive Capacity: 17 GiB Free, 18 GiB Total
Minioは9000ポートで起動しますので、WebブラウザやAPIでは9000ポートに接続します。試しに http://localhost:9000/
にアクセスすると、MinioのWebインターフェイスが表示されますので、ログインしていじってみます。この時、いくつかBucketを作成しておいてください。サンプルコードでBucketのリストを表示してみます。
ログにアクセスキーとシークレットキーが出力されるので、WebブラウザやAPIでアクセスするときはこれを使用します。自動テストなどでアクセスキーとシークレットキーを固定したい場合は、環境変数MINIO_ACCESS_KEY
とMINIO_SECRET_KEY
を指定することで、任意に設定できます。
SpringBootアプリケーションからMinioにアクセスしてみる
SpringBootプロジェクトの作成手順は割愛します。肝心のサンプルコードは、 src/main/java/me/u6k/sample_minio/Main.java
をご覧ください。一部をここで解説します。
@Value("${s3.url}")
private String s3url;
@Value("${s3.access-id}")
private String s3accessId;
@Value("${s3.secret-key}")
private String s3secretKey;
@Value("${s3.timeout}")
private int s3timeout;
設定情報として、S3エンドポイントURL、アクセスキー、シークレットキー、タイムアウト値(ミリ秒)を取得しています。SpringBootアプリケーションなので、application.properties
や環境変数で指定することができます。
AWSCredentials credentials = new BasicAWSCredentials(this.s3accessId, this.s3secretKey);
アクセスキーとシークレットキーを使用して認証情報を作成します。他に、証明書から認証情報を作成する方法もあるようです。
ClientConfiguration configuration = new ClientConfiguration();
configuration.setSocketTimeout(this.s3timeout);
configuration.setSignerOverride("AWSS3V4SignerType");
タイムアウト値と署名方法を指定します。ここら辺はおまじない。
AmazonS3 s3 = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withEndpointConfiguration(new EndpointConfiguration(this.s3url, "us-east-1"))
.withClientConfiguration(configuration)
.withPathStyleAccessEnabled(true)
.build();
認証情報、S3エンドポイント、クライアント設定情報、パス・スタイルを設定して、S3クライアントを初期化します。
S3エンドポイントは、URLのほかにリージョンを指定します。ここではus-east-1
をハードコードしていますが、Minioがデフォルトでus-east-1
のためです。
パス・スタイルについては、AWS S3におけるバケット名はDNS名であるのに対して、Minioはパスになるため、この指定が必要です。
for (Bucket bucket : s3.listBuckets()) {
L.info("bucket={}", bucket.getName());
}
バケットの一覧を取得して、バケット名をログ出力しています。
Dockerイメージをビルドして、Dockerコンテナからアクセスしてみる
まず、Dockerイメージをビルドします。
$ docker build -t sample-minio .
事前にMinioコンテナを起動して、バケットをいくつか作成しておき、sample-minioコンテナを起動します。
$ docker run \
--rm \
--link s3:s3 \
-e S3_URL=http://s3:9000/ \
-e S3_ACCESS-ID=xxxxxxxxxxxxxxxxxxxx \
-e S3_SECRET-KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
-e S3_TIMEOUT=10000 \
-v $HOME/.m2:/root/.m2 \
-v $(pwd):/var/my-app \
sample-minio
正常完了すると、以下のようにログ出力されます。
2017-04-30 09:14:54.463 INFO 1 --- [ main] me.u6k.sample_minio.Main : s3.url=http://s3:9000/
2017-04-30 09:14:54.476 INFO 1 --- [ main] me.u6k.sample_minio.Main : s3.access-id=xxxxxxxxxxxxxxxxxxxx
2017-04-30 09:14:54.476 INFO 1 --- [ main] me.u6k.sample_minio.Main : s3.secret-key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2017-04-30 09:14:54.476 INFO 1 --- [ main] me.u6k.sample_minio.Main : s3.timeout=10000
2017-04-30 09:14:57.357 INFO 1 --- [ main] me.u6k.sample_minio.Main : bucket=bar
2017-04-30 09:14:57.357 INFO 1 --- [ main] me.u6k.sample_minio.Main : bucket=boo
2017-04-30 09:14:57.357 INFO 1 --- [ main] me.u6k.sample_minio.Main : bucket=foo
おわりに
S3アクセスとクライアント初期化処理のみ異なりますが、他は同様にアクセスできることが確認できました。MinioはS3のローカル環境として利用できそうだと考えます。