前書き
本番環境ではAzure Blob Storageをオブジェクトストレージとして使用していますが、ローカル開発環境ではクラウド環境と切り離して開発したいと考え、Azure StorageのエミュレーターであるAzuriteを利用しました。
AzuriteをDockerComposeで構築する際に、Blobコンテナの作成までをCompose内で自動化しているケースがパッと見つかれなかったので本記事を作成しました。
対応方針
- Azurite(Azure Storage Emulator) をDocker Composeで立ち上げて、Azure Blob Storageの代替として使う。
- 起動時に Azurite の初期設定として、あらかじめBlobコンテナを作成する。
- Laravelのソースコードで、本番とローカルを環境変数だけで切り替えられるようにする。
実装
1. ライブラリのインストール
まず、Azure Blob Storage にアクセスするためのライブラリを Laravel プロジェクトに導入します。
composer require microsoft/azure-storage-blob
2. .env
の設定
クラウドのAzure Blob Storageではなく、ローカルのAzuriteに接続するための設定例です。AZURE_BLOB_CONNECTION_STRING
のAccountKeyについて、Base64形式でないと後続の「az storage container create」がエラーになったため、ダミーのBase64形式としています。
AZURE_BLOB_CONNECTION_STRING="DefaultEndpointsProtocol=http;AccountName=localblobaccount;AccountKey=Eby8vdM02xNo72UNZ4lCUQ==;BlobEndpoint=http://azurite:10000/localblobaccount"
AZURE_BLOB_ENDPOINT=http://localhost:10000/localblobaccount/local-container/
AZURE_BLOB_CONTAINER_NAME=local-container
3. docker-compose.yml
でAzuriteコンテナと初期設定のコンテナを追加
下記の例では azurite
というサービスでAzuriteを起動し、azurite-init
というサービスでBlobコンテナを作成するコマンドを実行しています。
version: '3.8'
services:
# ...(他のサービス設定など)
#*# Azurite (Azure Storage Emulator) #*#
azurite:
container_name: azurite_${APP_NAME}
image: mcr.microsoft.com/azure-storage/azurite:latest
ports:
- "10000:10000"
volumes:
- azurite-store:/data
environment:
AZURITE_ACCOUNTS: localblobaccount:Eby8vdM02xNo72UNZ4lCUQ==
restart: always
# Azurite上にcontainerを作成
azurite-init:
container_name: azurite_init_${APP_NAME}
image: mcr.microsoft.com/azure-cli
depends_on:
- azurite
entrypoint:
- "/bin/sh"
command:
- "-c"
- |
echo 'Waiting for azurite...'
sleep 3
az storage container create \
--name local-container \
--account-name localblobaccount \
--account-key Eby8vdM02xNo72UNZ4lCUQ== \
--blob-endpoint http://azurite:10000/localblobaccount \
--public-access blob
echo 'Done.'
volumes:
azurite-store:
上記では、azurite-init
コンテナで az storage container create ...
コマンドを実行し、Azurite上に local-container
というBlobコンテナを作成しています。--public-access blob
を指定しているため、特定のパスを直接URLで開くことが可能になります。
4. Laravelコントローラでファイルアップロード処理
以下は例として、ローカルの neko.jpg
をAzuriteにアップロードするコードです。createBlockBlob
メソッドでBlobへアップロードしています。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use MicrosoftAzure\Storage\Blob\BlobRestProxy;
use MicrosoftAzure\Storage\Blob\Models\CreateBlockBlobOptions;
use Illuminate\Support\Str;
class BlobSampleController extends Controller
{
public function uploadLocalImage()
{
// 環境変数から直接取得
$connectionString = env('AZURE_BLOB_CONNECTION_STRING');
$blobEndpoint = env('AZURE_BLOB_ENDPOINT');
$containerName = env('AZURE_BLOB_CONTAINER_NAME');
// Blobクライアントの生成
$blobClient = BlobRestProxy::createBlobService($connectionString);
// ローカルの画像ファイル(例:project_root/neko.jpg)を読み込み
$localFilePath = base_path('neko.jpg');
$content = fopen($localFilePath, 'r');
// アップロード先パスとファイル名をランダム生成(例:XXX/image/YYY.jpg)
$uploadPath = Str::random(10) . '/image/';
$fileName = Str::random(10) . '.jpg';
// Blobの作成オプション(ここでは MIME タイプを設定)
$options = new CreateBlockBlobOptions();
$options->setContentType('image/jpeg');
// アップロード実行
$blobClient->createBlockBlob(
$containerName,
$uploadPath . $fileName,
$content,
$options
);
// 成功レスポンス(URL を含む)
return response()->json([
'message' => 'アップロード成功',
'blob_url' => $blobEndpoint . $uploadPath . $fileName,
]);
}
}
実装後、Laravelプロジェクトを起動して uploadLocalImage()
を呼び出すと、Azuriteに対して画像がアップロードされます。JSONレスポンスに含まれる blob_url
にアクセスすると、実際にアップロードされた画像をブラウザから確認できます。
参考
- ローカルでの Azure Storage の開発に Azurite エミュレーターを使用する
- 【Laravel】Azure Blob Storageを使ってみる - Qiita
- Azure Blob Storage を扱う Python アプリの開発環境を Docker で作る - Qiita
どなたかの参考になれば嬉しいです!