Azure Storage アクセスガイド
Frontend/Backend アプリケーションから Azure Blob Storage と File Share にアクセスする方法を説明します。
概要
各環境(dev/prd)では、Frontend/Backend ごとに以下のストレージリソースが提供されます:
ストレージ構成: Storage Account → File Shares(Frontend/Backend ごとに /mnt/data にマウント)、Blob Containers(Frontend/Backend ごとに分離)
用途の違い:
- File Share: コンテナに
/mnt/dataとしてマウント可能、通常のファイル I/O、設定ファイル・一時ファイル・共有データに適している - Blob Storage: マウント不可・API アクセスのみ、Azure SDK、画像・動画・大容量ファイル・アーカイブに適している
環境変数
enable_storage = true の場合、以下の環境変数が自動的に設定されます:
共通環境変数: AZURE_STORAGE_ACCOUNT_NAME, AZURE_STORAGE_ACCOUNT_KEY, AZURE_STORAGE_CONNECTION_STRING, AZURE_STORAGE_BLOB_ENDPOINT, AZURE_STORAGE_CONTAINER_NAME
注意: AZURE_STORAGE_CONTAINER_NAME は Frontend/Backend で異なる値が設定されます。
File Share (ファイル共有) へのアクセス
マウントパス: /mnt/data(Frontend/Backend ともに同じパスですが、異なる File Shareがマウントされているため、データは分離されています)
アクセス方法: 通常のファイルシステム操作で読み書きできます。
Python (Backend) の例
import os
# ファイルの書き込み
with open('/mnt/data/config.json', 'w') as f:
f.write('{"key": "value"}')
# ファイルの読み込み
with open('/mnt/data/config.json', 'r') as f:
data = f.read()
# ディレクトリの作成
os.makedirs('/mnt/data/uploads', exist_ok=True)
# ファイルの存在チェック
if os.path.exists('/mnt/data/config.json'):
print("File exists")
# ファイル一覧の取得
files = os.listdir('/mnt/data')
Node.js (Frontend) の例
const fs = require("fs");
const path = require("path");
// ファイルの書き込み
fs.writeFileSync("/mnt/data/config.json", JSON.stringify({ key: "value" }));
// ファイルの読み込み
const data = fs.readFileSync("/mnt/data/config.json", "utf8");
const config = JSON.parse(data);
// ディレクトリの作成
fs.mkdirSync("/mnt/data/uploads", { recursive: true });
// ファイルの存在チェック
if (fs.existsSync("/mnt/data/config.json")) {
console.log("File exists");
}
// ファイル一覧の取得
const files = fs.readdirSync("/mnt/data");
ユースケース
- ✅ アプリケーション設定ファイルの保存
- ✅ セッションデータの永続化
- ✅ 一時ファイルの保存(アップロード中のファイルなど)
- ✅ ログファイルの保存
- ✅ キャッシュファイルの保存
Blob Storage へのアクセス
認証情報の取得
環境変数から接続情報を取得します:
import os
connection_string = os.getenv("AZURE_STORAGE_CONNECTION_STRING")
container_name = os.getenv("AZURE_STORAGE_CONTAINER_NAME")
Python (Backend) でのアクセス
インストール
pip install azure-storage-blob
基本的な使用方法
import os
from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient
# 接続情報を環境変数から取得
connection_string = os.getenv("AZURE_STORAGE_CONNECTION_STRING")
container_name = os.getenv("AZURE_STORAGE_CONTAINER_NAME")
# BlobServiceClient の作成
blob_service_client = BlobServiceClient.from_connection_string(connection_string)
container_client = blob_service_client.get_container_client(container_name)
# ファイルのアップロード
def upload_file(file_path, blob_name):
"""ファイルをBlobにアップロード"""
blob_client = container_client.get_blob_client(blob_name)
with open(file_path, "rb") as data:
blob_client.upload_blob(data, overwrite=True)
print(f"Uploaded {blob_name}")
# ファイルのダウンロード
def download_file(blob_name, download_path):
"""Blobからファイルをダウンロード"""
blob_client = container_client.get_blob_client(blob_name)
with open(download_path, "wb") as download_file:
download_file.write(blob_client.download_blob().readall())
print(f"Downloaded {blob_name}")
# Blob一覧の取得
def list_blobs():
"""Containerに存在するBlobの一覧を取得"""
blob_list = container_client.list_blobs()
for blob in blob_list:
print(f"Name: {blob.name}, Size: {blob.size} bytes")
# Blobの削除
def delete_blob(blob_name):
"""Blobを削除"""
blob_client = container_client.get_blob_client(blob_name)
blob_client.delete_blob()
print(f"Deleted {blob_name}")
# Blobの存在チェック
def blob_exists(blob_name):
"""Blobが存在するかチェック"""
blob_client = container_client.get_blob_client(blob_name)
return blob_client.exists()
FastAPI での使用例
from fastapi import FastAPI, UploadFile, File
from azure.storage.blob import BlobServiceClient
import os
app = FastAPI()
connection_string = os.getenv("AZURE_STORAGE_CONNECTION_STRING")
container_name = os.getenv("AZURE_STORAGE_CONTAINER_NAME")
blob_service_client = BlobServiceClient.from_connection_string(connection_string)
container_client = blob_service_client.get_container_client(container_name)
@app.post("/upload")
async def upload_file(file: UploadFile = File(...)):
"""ファイルをBlobにアップロード"""
blob_client = container_client.get_blob_client(file.filename)
content = await file.read()
blob_client.upload_blob(content, overwrite=True)
return {"filename": file.filename, "size": len(content)}
@app.get("/files")
async def list_files():
"""Blob一覧を取得"""
blob_list = container_client.list_blobs()
files = [{"name": blob.name, "size": blob.size} for blob in blob_list]
return {"files": files}
@app.get("/download/{filename}")
async def download_file(filename: str):
"""Blobからファイルをダウンロード"""
blob_client = container_client.get_blob_client(filename)
if not blob_client.exists():
return {"error": "File not found"}
blob_data = blob_client.download_blob().readall()
return Response(content=blob_data, media_type="application/octet-stream")
Node.js (Frontend) でのアクセス
インストール
npm install @azure/storage-blob
基本的な使用方法
const { BlobServiceClient } = require("@azure/storage-blob");
// 接続情報を環境変数から取得
const connectionString = process.env.AZURE_STORAGE_CONNECTION_STRING;
const containerName = process.env.AZURE_STORAGE_CONTAINER_NAME;
// BlobServiceClient の作成
const blobServiceClient =
BlobServiceClient.fromConnectionString(connectionString);
const containerClient = blobServiceClient.getContainerClient(containerName);
// ファイルのアップロード
async function uploadFile(filePath, blobName) {
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
const fs = require("fs");
const data = fs.readFileSync(filePath);
await blockBlobClient.upload(data, data.length);
console.log(`Uploaded ${blobName}`);
}
// ファイルのダウンロード
async function downloadFile(blobName, downloadPath) {
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
const fs = require("fs");
const downloadBlockBlobResponse = await blockBlobClient.download(0);
const writeStream = fs.createWriteStream(downloadPath);
downloadBlockBlobResponse.readableStreamBody.pipe(writeStream);
console.log(`Downloaded ${blobName}`);
}
// Blob一覧の取得
async function listBlobs() {
const blobs = [];
for await (const blob of containerClient.listBlobsFlat()) {
blobs.push({ name: blob.name, size: blob.properties.contentLength });
}
return blobs;
}
// Blobの削除
async function deleteBlob(blobName) {
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
await blockBlobClient.delete();
console.log(`Deleted ${blobName}`);
}
// Blobの存在チェック
async function blobExists(blobName) {
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
return await blockBlobClient.exists();
}
Next.js API Routes での使用例
// pages/api/upload.js
import { BlobServiceClient } from "@azure/storage-blob";
import formidable from "formidable";
import fs from "fs";
export const config = {
api: {
bodyParser: false,
},
};
const connectionString = process.env.AZURE_STORAGE_CONNECTION_STRING;
const containerName = process.env.AZURE_STORAGE_CONTAINER_NAME;
export default async function handler(req, res) {
if (req.method !== "POST") {
return res.status(405).json({ error: "Method not allowed" });
}
const form = formidable({});
const [fields, files] = await form.parse(req);
const file = files.file[0];
const blobServiceClient =
BlobServiceClient.fromConnectionString(connectionString);
const containerClient = blobServiceClient.getContainerClient(containerName);
const blockBlobClient = containerClient.getBlockBlobClient(
file.originalFilename
);
const data = fs.readFileSync(file.filepath);
await blockBlobClient.upload(data, data.length);
res.status(200).json({
filename: file.originalFilename,
size: file.size,
});
}
ユースケース
- ✅ ユーザーアップロードファイルの保存(画像、動画、PDF 等)
- ✅ バックアップファイルの保存
- ✅ レポートやエクスポートファイルの生成・保存
- ✅ メディアファイルの CDN 配信
- ✅ 大容量データのアーカイブ
使用例
シナリオ 1: ユーザーがアップロードした画像を保存
Backend (FastAPI):
from fastapi import FastAPI, UploadFile, File
from azure.storage.blob import BlobServiceClient
import os
from datetime import datetime
app = FastAPI()
connection_string = os.getenv("AZURE_STORAGE_CONNECTION_STRING")
container_name = os.getenv("AZURE_STORAGE_CONTAINER_NAME")
blob_service_client = BlobServiceClient.from_connection_string(connection_string)
container_client = blob_service_client.get_container_client(container_name)
@app.post("/upload-image")
async def upload_image(file: UploadFile = File(...)):
# ユニークなファイル名を生成
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
blob_name = f"/img/{timestamp}_{file.filename}"
# Blobにアップロード
blob_client = container_client.get_blob_client(blob_name)
content = await file.read()
blob_client.upload_blob(content, overwrite=True)
# URLを生成(公開URLが必要な場合はSASトークンを使用)
blob_url = blob_client.url
return {
"filename": file.filename,
"blob_name": blob_name,
"url": blob_url,
"size": len(content)
}
シナリオ 2: 設定ファイルを File Share に保存
Backend (Python):
import json
import os
def save_user_config(user_id: str, config: dict):
"""ユーザー設定をFile Shareに保存"""
config_dir = f"/mnt/data/configs/{user_id}"
os.makedirs(config_dir, exist_ok=True)
config_file = f"{config_dir}/settings.json"
with open(config_file, 'w') as f:
json.dump(config, f, indent=2)
print(f"Saved config for user {user_id}")
def load_user_config(user_id: str) -> dict:
"""ユーザー設定をFile Shareから読み込み"""
config_file = f"/mnt/data/configs/{user_id}/settings.json"
if not os.path.exists(config_file):
return {}
with open(config_file, 'r') as f:
return json.load(f)
シナリオ 3: レポート生成と Blob 保存
Backend (Python):
import pandas as pd
from io import BytesIO
from azure.storage.blob import BlobServiceClient
import os
def generate_and_save_report(data: list, report_name: str):
"""データからレポートを生成してBlobに保存"""
# DataFrameを作成
df = pd.DataFrame(data)
# ExcelファイルをメモリにExcel生成
excel_buffer = BytesIO()
df.to_excel(excel_buffer, index=False, engine='openpyxl')
excel_buffer.seek(0)
# Blobにアップロード
connection_string = os.getenv("AZURE_STORAGE_CONNECTION_STRING")
container_name = os.getenv("AZURE_STORAGE_CONTAINER_NAME")
blob_service_client = BlobServiceClient.from_connection_string(connection_string)
container_client = blob_service_client.get_container_client(container_name)
blob_name = f"reports/{report_name}.xlsx"
blob_client = container_client.get_blob_client(blob_name)
blob_client.upload_blob(excel_buffer.getvalue(), overwrite=True)
return blob_client.url
トラブルシューティング
File Share にアクセスできない
症状: /mnt/data にファイルを書き込めない
原因と対処:
enable_storage = trueが設定されているか確認- Terraform が正しく apply されているか確認
- Container App が再起動されているか確認(設定変更後)
# File Shareが正しくマウントされているか確認
ls -la /mnt/data
# 書き込み権限があるか確認
touch /mnt/data/test.txt
Blob Storage に接続できない
症状: AuthenticationError や ResourceNotFoundError
原因と対処:
- 環境変数が正しく設定されているか確認:
import os
print(os.getenv("AZURE_STORAGE_CONNECTION_STRING"))
print(os.getenv("AZURE_STORAGE_CONTAINER_NAME"))
-
Container 名が正しいか確認(Frontend/Backend で異なる)
-
Storage Account のアクセスキーが正しいか確認
パフォーマンスが遅い
File Share:
- 大量の小さなファイルへのアクセスは遅い
- 可能な限りファイルを結合するか、Blob を使用
Blob Storage:
- 同時アクセス数に制限がある場合、CDN の利用を検討
- 大容量ファイルは並列アップロード/ダウンロードを使用
# 並列アップロード例
from azure.storage.blob import BlobServiceClient
blob_client.upload_blob(
data,
overwrite=True,
max_concurrency=4 # 並列度を指定
)
まとめ
- File Share (
/mnt/data): 設定ファイル、一時ファイル、キャッシュに最適 - Blob Storage: 大容量ファイル、メディアファイル、アーカイブに最適
- Frontend/Backend で環境変数は自動設定される
- Frontend/Backend で異なる Storage リソースが割り当てられる
適切なストレージを選択して、効率的なアプリケーションを構築してください!