はじめに
この記事は セゾン情報システムズ Advent Calendar 2020 13日目の記事です。
Azuriteは非常に便利なツールなのですが、日本語の情報が殆どないので書きました。
Azuriteとは
Azureのストレージサービスをローカルでエミュレートできるという代物です。AWSのS3でいうminioのようなものですね。
詳しくは公式ドキュメントを参照あれ。
Azurite オープンソース エミュレーターには、Azure Blob およびキュー ストレージ アプリケーションをテストするための無料のローカル環境が用意されています。 ローカルでのアプリケーションの動作に満足できたら、クラウドでの Azure Storage アカウントの使用に切り替えることができます。 エミュレーターは、Windows、Linux、および macOS でのクロスプラットフォーム サポートを提供します。
AzuriteはVSCodeの拡張機能やnpmパッケージ、dockerイメージなどの形で配布されています。
今回はDockerイメージ形式で利用していきます。
また、今回はBlobストレージのエミュレーティングを利用してみます。
参考
SDKの公式クイックスタート - https://docs.microsoft.com/ja-jp/azure/storage/blobs/storage-quickstart-blobs-java
AzuriteのGithub - https://github.com/azure/azurite
環境
- OS : macOS Catalina 10.15.6
- Java : AdoptOpenJDK11 14.0.2
- Docker : 19.03.12
- AzureSDK : com.azure:azure-storage-blob:12.8.0
Azuriteの起動
まずは公式ドキュメントにある通り、Dockerイメージをプルして起動します。
なお、バックグラウンド実行したいので公式ドキュメントのコマンドに-d
を追加しています
$ docker pull mcr.microsoft.com/azure-storage/azurite
Using default tag: latest
latest: Pulling from azure-storage/azurite
cbdbe7a5bc2a: Pull complete
9287919c3a0f: Pull complete
43a47bbd54c9: Pull complete
3c1bcea295c4: Pull complete
5047118b6920: Pull complete
77c92003e19f: Pull complete
13ec4a55a3c3: Pull complete
21145ef27392: Pull complete
db43acfda40e: Pull complete
Digest: sha256:6b6c9c24e97a6c000a81503a41bbf366f04c23aa3b473bfc27267145c92eeceb
Status: Downloaded newer image for mcr.microsoft.com/azure-storage/azurite:latest
mcr.microsoft.com/azure-storage/azurite:latest
$ docker run -d -p 10000:10000 -p 10001:10001 \
mcr.microsoft.com/azure-storage/azurite
fc6aba0b5929aa2b7fcb9fb7d2b51d2b9e06c31c0d5486cce580798f7e844eef
Azuriteでは、接続文字列は以下の2つになり、どちらでも繋がります。2つ目のほうが本物のAzureBlobストレージに近い形式ですね。
UseDevelopmentStorage=true
もしくは
DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;
Azuriteにデータを作る
本当はDockerの起動時にマウントするなどしてデータを持たせたいのだが、中を見てみると一見して理解できない構造でデータを持っているようで、それができないでいる。
詳しい人いたら教えて下さい。。。
Azure Storage Explorerから作る
Azure Storage ExplorerというツールでGUIからデータを作成できます。
JavaからSDKを使ってアクセスする
クイックスタートに従ってJavaからアクセスしてみます。
build.gradle
に依存関係を追加します。
dependencies {
compile 'com.azure:azure-storage-blob:12.8.0' // 追加
}
コンテナ名、オブジェクト名、オブジェクトの最終更新日時を表示してみます。
import com.azure.core.http.rest.PagedIterable;
import com.azure.storage.blob.BlobContainerClient;
import com.azure.storage.blob.BlobServiceClient;
import com.azure.storage.blob.BlobServiceClientBuilder;
import com.azure.storage.blob.models.BlobContainerItem;
public class AzureSdkApp {
public static void main(String[] args) {
final BlobServiceClient blobClient = new BlobServiceClientBuilder().connectionString("UseDevelopmentStorage=true").buildClient();
final PagedIterable<BlobContainerItem> containers = blobClient.listBlobContainers();
containers.forEach(container -> {
final String containerName = container.getName();
System.out.println("containerName = " + containerName);
final BlobContainerClient containerClient = blobClient.getBlobContainerClient(containerName);
containerClient.listBlobs().forEach(blob -> {
final String blobName = blob.getName();
System.out.println("blobName = " + blobName);
System.out.println("blob.getProperties().getLastModified() = " + blob.getProperties().getLastModified());
});
System.out.println("==========");
});
}
}
実行結果(Azuriteにデータを作ってあります)
containerName = container-1
blobName = folder-1/test.txt
blob.getProperties().getLastModified() = 2020-12-12T05:14:36Z
blobName = test.txt
blob.getProperties().getLastModified() = 2020-12-12T05:14:53Z
==========
containerName = container-2
==========
とこんな感じでAzureSDKを使ったプログラムの動作確認環境としても、Azuriteは便利です。
AzureSDKも非常に使いやすいですね。(この記事を書いている最中に、この記事を書くきっかけになったハマリポイントをかんたんに解決する方法が見つかったのは内緒)
ぜひ皆さん使ってみてください〜〜
おまけ:Javaからコンテナの起動、オブジェクトの作成もやってみる
上記のコードのテストを書きたくなったときなど、Javaからコンテナの起動・オブジェクトの作成もしたくなる場合があると思います。
そんなときはtestcontainersを使ってJavaからコンテナを操作します。
build.gradle
に依存関係を追加します。
dependencies {
compile 'com.azure:azure-storage-blob:12.8.0'
compile 'org.testcontainers:testcontainers:1.14.3' // 追加
}
GenericContainer
を継承したAzuriteContainer
クラスを作成します。
接続文字列内のBlobEndpoint
のホスト名がlocalhost
になっていることに注意!
127.0.0.1だと繋がりません
import org.testcontainers.containers.GenericContainer;
public class AzuriteContainer extends GenericContainer {
public AzuriteContainer() {
super("mcr.microsoft.com/azure-storage/azurite");
}
@Override
protected void configure() {
super.configure();
addFixedExposedPort(10000, 10000);
}
public String getConnectionString() {
return "DefaultEndpointsProtocol=http;" +
"AccountName=devstoreaccount1;" +
"AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;" +
"BlobEndpoint=http://localhost:10000/devstoreaccount1";
}
}
テストコード内から起動・オブジェクトの作成をしてみます。
import com.azure.storage.blob.BlobContainerClient;
import com.azure.storage.blob.BlobServiceClient;
import com.azure.storage.blob.BlobServiceClientBuilder;
import com.azure.storage.blob.models.BlobItem;
import com.azure.storage.blob.specialized.BlockBlobClient;
import com.example.azuresdktest.container.AzuriteContainer;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
class AzureSdkAppTest {
@Test
void azureTest() throws IOException {
try(final AzuriteContainer azuriteContainer = new AzuriteContainer()) {
azuriteContainer.start(); // コンテナの起動
final BlobServiceClient serviceClient = new BlobServiceClientBuilder().connectionString(azuriteContainer.getConnectionString()).buildClient();
final String containerName = "test-container";
serviceClient.createBlobContainer(containerName); // コンテナの作成
final BlobContainerClient containerClient = serviceClient.getBlobContainerClient(containerName);
final String blobName = "testFile.txt";
final BlockBlobClient blobClient = containerClient.getBlobClient(blobName).getBlockBlobClient();
final String data = "Hello world!";
InputStream dataStream = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
blobClient.upload(dataStream, data.length()); // ファイルのアップロード
dataStream.close();
// verify
for (BlobItem listBlob : containerClient.listBlobs()) {
System.out.println(listBlob.getName());
}
}
}
}
実行結果
testFile.txt
上記のコードはGithubのexampleを参考にしました。
私は利用したことはないのですが、SDKでファイルをダウンロードなどもできるようですね。とても便利だ!