🖼️

GPT-image-1 × Streamlit で作る画像生成AIアプリ - Entra ID認証連携からAzureデプロイまで完全解説

に公開

はじめに

OpenAIが提供する先進的な画像生成モデル「GPT-image-1」は、Azure AIプラットフォームにも統合され、ますます利用しやすくなっています。この記事では、このGPT-image-1と、Pythonで迅速にWeb UIを構築できる「Streamlit」を組み合わせたアプリケーション開発の全工程を、最新情報に基づいて解説します。ローカルでの開発・検証から始まり、Dockerコンテナ化、そしてAzureのPaaS(App Service for Containers / Container Apps)へのデプロイまで、一連の流れをステップバイステップで追っていきます。

特に、エンタープライズ環境で不可欠となるMicrosoft Entra ID (旧 Azure AD) による認証や、Azure Key Vaultを用いた安全なシークレット管理、さらにはAzure Container Registry (ACR) を利用したCI/CD連携の基礎についても具体的に触れていきます。「LLMを使ったWebアプリ開発は初めて」「Azureへのデプロイ手順を最新情報で知りたい」という方でも、この記事を読み進めることで、実際に動作するセキュアなAIアプリケーションをクラウド上に構築できるようになることを目指します。

本記事で解説するアプリケーションの完全なソースコードは、以下のGitHubリポジトリで公開しています。実装の詳細を確認したい場合や、すぐに動かしてみたい場合は、こちらも合わせてご参照ください。

https://github.com/naoki1213mj/gpt-image-1-streamlit

さあ、一緒にクラウドネイティブなAIアプリ開発の世界にDeep diveしましょう!

1 アプリ概要と技術スタック

まずは、今回作成するアプリケーションの概要と、使用する主要な技術について、2025年5月現在の状況を踏まえて整理します。

1.1 作るもの

このプロジェクトでは、テキストプロンプトから画像を生成する「Text to Image (txt2img)」と、アップロードした画像を基に編集する「Image to Image (img2img)」という二つの主要な画像生成モードを備えたWebアプリケーションを目指します(img2imgのAzure実装については後述の注意点があります)。

5/1よりAzure AI FoundryのImage Playgroundからgpt-image-1などの画像生成モデルが簡単に試せるようになっており、今回作成するStreamlitアプリのイメージと近いです。
https://devblogs.microsoft.com/foundry/images-playground-may-2025/

さらに、使いやすさを考慮し、アイデア出しを助けるプロンプト例のワンクリックボタンや、生成前後の画像を比較表示する機能も実装します。将来的には、過去の生成履歴をサムネイルで一覧できるギャラリー機能の追加も視野に入れています。初めてのユーザーでもスムーズに利用できるよう、操作方法を案内するチュートリアル表示 (st.dialog を使用) も設けます。

完成イメージ:ツイート内の2動画はそれぞれtxt2imgとimg2imgで画像生成や編集後の様子を撮影↓
https://x.com/chipsnack0711/status/1918192939832099196

認証面では、Azure環境でのMicrosoft Entra IDによるシングルサインオン(Easy Auth連携)と、ローカル開発用の簡易認証をサポートします。バックエンドは、OpenAI APIとAzure OpenAI Service APIの両方に対応し、設定で切り替え可能な柔軟性を持たせます。GitHubリポジトリのコードでは、これらの機能が具体的に実装されています。

1.2 GPT-image-1 とは (2025年5月最新情報)

GPT-image-1は、OpenAIによって開発された最先端の画像生成・編集モデルです。その最大の特徴は、テキストによる指示(プロンプト)に対する高い理解度と、それに基づいて高品質かつ多様な画像を生成できる能力にあります。

https://youtu.be/btA8njJjLXY

しかし、単に高画質な画像を生成するだけでなく、生成プロセスを細かく制御するための多様なパラメータが用意されている点も、GPT-image-1の大きな魅力です。主なカスタマイズオプションとしては、以下のようなものが挙げられます(利用可能なオプションはモデルバージョンやAPIによって異なる場合があります)。

  • size: 生成される画像の解像度を指定します。例えば "1024x1024", "1792x1024", "1024x1792" など、モデルがサポートするアスペクト比と解像度の中から選択できます。
  • quality: 画像の品質レベルを選択します。"standard" は標準品質で高速な生成、"hd" はより精細でディテールに富んだ画像を生成しますが、処理時間が長くなる傾向があります。
  • style: 生成される画像の全体的な美的スタイルを調整します。"vivid" を指定すると、より鮮やかでドラマチック、超現実的な雰囲気の画像が生成されやすくなります。一方、"natural" を指定すると、より写実的で自然な見た目の画像が生成される傾向があります。
  • response_format: APIからのレスポンス形式を指定します。"url" を指定すると一時的にアクセス可能な画像のURLが返され、"b64_json" を指定するとBase64エンコードされた画像データそのものがJSON形式で返されます。アプリケーションの要件に応じて選択します。
  • n: 一度のAPIコールで生成する画像の枚数を指定します(通常は1枚)。

これらのパラメータを組み合わせることで、ユーザーは単なるテキストプロンプトだけでなく、より具体的な要求に合わせて生成結果を調整することが可能になります。

Azureにおける展開: Azureプラットフォームでは、統合開発環境である Azure AI Foundry を通じてGPT-image-1へのアクセスと利用がサポートされています。特に、Azure AI Foundry内の「プレイグラウンド」機能は強力で、上記のような各種パラメータ(サイズ、品質、スタイルなど)をGUI上でインタラクティブに試しながら、プロンプトの効果をリアルタイムで確認できます。このプレイグラウンドでの試行錯誤を通じて得られた最適なパラメータ設定を、実際のアプリケーション開発におけるAPI呼び出しに反映させることが可能です。

https://learn.microsoft.com/ja-jp/azure/ai-foundry/what-is-azure-ai-foundry

APIアクセス: Azure OpenAI Service経由でのAPIアクセスも提供されており、2025年5月現在、APIバージョン 2024-07-01-preview や、より新しいプレビューバージョン (例: 2025-04-01-preview など、利用可能な最新バージョンを確認してください) を指定することで利用可能です。ただし、利用可能なリージョンや最新のAPIバージョン、モデルの機能(例: img2imgサポート状況、パラメータの詳細)については、変更される可能性があるため、常にAzure OpenAI Serviceの公式ドキュメントで最新情報を確認することが重要です。

https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/models?tabs=global-standard%2Cstandard-chat-completions#image-generation-models

1.3 Streamlit とは

Streamlitは、PythonスクリプトだけでインタラクティブなデータアプリケーションやWeb UIを迅速に構築できるオープンソースフレームワークです。データサイエンティストやPythonエンジニアが、フロントエンドの複雑な知識(HTML, CSS, JavaScript)なしに、分析結果の可視化や簡単なツールのプロトタイピングを行うのに非常に適しています。

ボタン、スライダー、テキスト入力、ファイルアップロードといった様々なUIウィジェットの追加や、データフレーム、チャート、そしてもちろん画像の表示などが、非常に少ないPythonコード量で直感的に実装できます。

https://streamlit.io/

認証機能のサポートも継続的に改善されており、Microsoft Entra IDとの連携も依然として有効な選択肢の一つです。

https://docs.streamlit.io/develop/tutorials/authentication

2 事前準備

開発を始める前に、必要なツールとAzureリソースを準備しましょう。

2.1 開発環境

スムーズな開発のためには、適切な基盤を整えることが重要です。OSとしてはmacOSまたはLinuxディストリビューションを推奨します。Windows環境では、コンテナ技術との親和性が高いWSL 2 (Windows Subsystem for Linux 2) の利用が良いでしょう。Pythonのバージョンは3.10以上が必要で、この記事では3.12を想定しています。

パッケージ管理には、uv の使用を強く推奨します。これはRustで書かれた非常に高速なPythonパッケージインストーラー兼リゾルバーであり、従来の pipvenv の機能を兼ね備えつつ、仮想環境の作成やパッケージのインストール、依存関係の解決を劇的に高速化します。ディスク使用量の効率性も向上するため、開発サイクル全体の効率アップに貢献します。

https://github.com/astral-sh/uv

uvのインストールから仮想環境のセットアップ、基本的な依存パッケージのインストールまでの手順は以下の通りです。

# uvのインストール (macOS Homebrew例)
brew install uv
# (Linuxの場合は公式スクリプトなどを参照)

# プロジェクトディレクトリ作成と移動
mkdir gpt-image-1-streamlit && cd gpt-image-1-streamlit

# uvで仮想環境を作成 (.venvディレクトリ、Python 3.12を指定)
uv venv .venv --python 3.12

# 仮想環境の有効化 (macOS/Linux)
source .venv/bin/activate
# (Windowsの場合は適切なスクリプトを実行)

# 必須パッケージのインストール (2025年5月時点)
uv pip install streamlit "openai>=1.20.0" "openai[datalib]" azure-identity python-dotenv pillow azure-keyvault-secrets "azure-appconfiguration[azure-identity]" requests

開発が進み依存関係が固まった段階で、uv pip freeze > requirements.txt を実行し、その時点でのパッケージとそのバージョンを記録した requirements.txt ファイルを作成します。このファイルをGitで管理することで、他の開発者やCI/CDパイプラインが uv pip sync requirements.txt コマンドを実行すれば、全く同じ環境を高速に再現できるようになり、環境差異による問題を効果的に防止できます。

2.2 Azure リソース

次に、アプリケーションをクラウド上で動かすために必要なAzureサービスを準備します。Azureアカウントと有効なサブスクリプションがあることが前提です。主に以下のサービスを利用します。

目的 サービス名 備考
コンテナイメージの保管 Azure Container Registry (ACR) プライベートなDockerイメージレジストリ
PaaS実行環境① (Webアプリ向け) App Service for Containers LinuxベースのWebアプリ実行環境、カスタムコンテナ対応
PaaS実行環境② (マイクロサービス向け) Azure Container Apps (ACA) サーバーレスコンテナ実行環境、Kubernetesベース、スケーラビリティが高い
機密情報(APIキー等)の管理 Azure Key Vault シークレット、キー、証明書を安全に保管
ユーザー認証 Microsoft Entra ID Azure ADの後継、IDaaS
(オプション) 高度な設定管理 Azure App Configuration 機能フラグやアプリケーション設定を一元管理

どのPaaS実行環境(App ServiceかACAか)を選択するかは、アプリケーションの特性や将来的な拡張計画、運用管理の好みによって決まります。App Serviceは長年の実績があり設定が比較的直感的ですが、ACAはよりモダンなアーキテクチャを採用し、マイクロサービス関連機能(Dapr連携、KEDAによるイベント駆動スケーリングなど)が充実しています。本記事では両方のデプロイ手順を示すため、ご自身の状況に合わせて選択できます。

3 プロジェクトセットアップ

開発環境とAzureリソースの準備ができたら、プロジェクトの基本的な構造を整えます。

3.1 最終的なディレクトリ構成(例)

プロジェクトの骨格となるファイル構成を示します。

gpt-image-1-streamlit/
├── .venv/                    # uvによって作成された仮想環境 (Git管理外)
├── app.py                    # Streamlitアプリケーション本体のPythonスクリプト
├── requirements.txt          # `uv pip freeze > requirements.txt` で生成
├── .env.example              # .envファイルのテンプレート
├── .env                      # ローカル開発用の環境変数ファイル (★Git管理外)
├── .streamlit/               # Streamlit設定ディレクトリ
│   ├── config.toml           # Streamlitの動作設定
│   └── secrets.toml          # Streamlitのシークレット管理ファイル (★Git管理外)
├── Dockerfile                # アプリケーションをコンテナ化するための定義ファイル
├── .dockerignore             # Dockerイメージに含めないファイル・ディレクトリを指定
├── static/                   # (オプション) CSSファイルなどを配置
│   └── theme.css
└── README.md                 # プロジェクトの説明ファイル

3.2 仮想環境と依存パッケージのインストール

このステップは、「2.1 開発環境」で説明した uv venv および uv pip install コマンドの実行に該当します。開発中に新たなライブラリが必要になった場合は、適宜 uv pip install <package-name> で追加し、最後に uv pip freeze > requirements.txt でリストを更新しましょう。

3.3 .env ファイルと secrets.toml ファイル

APIキーやパスワードといった機密情報をコードに直接記述することは、セキュリティ上の重大なリスクです。ローカル開発においては、以下のファイルを使ってこれらを安全に管理します。

まず、標準的な環境変数ファイルである .env を作成します。ここには、OPENAI_API_KEYAZURE_OPENAI_ENDPOINT など、アプリケーションが実行時に必要とする値を記述します。python-dotenv ライブラリが、アプリケーション起動時にこのファイルの内容を環境変数として読み込んでくれます。この .env ファイルは、絶対にGitリポジトリにコミットしてはいけません。 プロジェクトの .gitignore ファイルに .env を必ず追加してください。他の開発者がどの設定項目が必要か分かるように、設定名だけを記述した .env.example ファイルを用意しておくと親切です。

次に、Streamlit固有の設定ファイルである .streamlit/secrets.toml があります。これはTOML形式で記述され、特にStreamlit Cloudへのデプロイや、Streamlit標準のOAuth機能 (st.login() など) を使う際のクライアントIDやシークレットを設定するのに便利です。コード内からは st.secrets["key_name"] のようにして値にアクセスできます。この secrets.toml ファイルも同様に、絶対にGitにコミットせず、.gitignore に追加してください。

これらの機密ファイルを誤って公開リポジトリにプッシュしてしまう事故を防ぐため、GitHubなどのプラットフォームが提供する Secret ScanningPush Protection といった機能を有効にしておくことを強く推奨します。これらの機能は、コミット内容に既知の形式のシークレットが含まれていないかを自動でチェックし、もし含まれていた場合はプッシュをブロックしてくれるため、意図しない情報漏洩の防止に役立ちます。

https://docs.github.com/ja/enterprise-cloud@latest/code-security/secret-scanning/about-secret-scanning

3.4 config.toml ファイル

.streamlit/config.toml ファイルを使うと、Streamlitアプリケーションの挙動や外観(テーマ)を細かく調整できます。例えば、以下のように設定できます。

.streamlit/config.toml
[theme]
# ダークテーマをデフォルトに設定
base = "dark"
primaryColor = "#FF4B4B" # アクセントカラー
backgroundColor = "#0E1117" # 背景色
secondaryBackgroundColor = "#262730" # サイドバーなどの背景色
textColor = "#FAFAFA" # テキスト色

[server]
# ファイル保存時にアプリケーションを自動でリロードする
runOnSave = true
# クロスサイトリクエストフォージェリ (XSRF) 保護を有効にする (セキュリティ上推奨)
enableXsrfProtection = true
# CORS (Cross-Origin Resource Sharing) 設定 (通常はデフォルトで問題ないことが多い)
# enableCORS = false

[browser]
# Streamlitの利用統計情報の収集を無効にする
gatherUsageStats = false

[logger]
# アプリケーションのログレベルを設定 (debug, info, warning, error)
level = "info"

特に enableXsrfProtection = true は、ユーザー入力やセッションを扱うアプリケーションにおいてセキュリティを強化するために推奨される設定です。

4 Streamlit アプリ実装 (app.py)

いよいよアプリケーション本体のコードを記述していきます。主要な機能の実装ポイントを解説します。完全なコードは、先に紹介した筆者のGitHubリポジトリをご参照ください。

https://github.com/naoki1213mj/gpt-image-1-streamlit/blob/main/app.py

4.1 UI/UX 設計のポイント

Streamlitが提供する多様なウィジェットを効果的に組み合わせることで、ユーザーにとって直感的で使いやすいインターフェースを構築することを目指します。

ユーザーの入力を支援するために、プロンプトは st.text_area で自由に入力できるようにしつつ、よく使われるプロンプトの例や、「アニメ風」「写実的」といったスタイル指定の例を st.button として配置し、クリックするとテキストエリアに挿入されるようにすると、ユーザーはスムーズに画像生成を開始できます。

詳細な設定項目、例えば生成する画像のサイズ、品質、枚数などは、そのまま表示するとUIが煩雑になりがちです。そこで st.expander("詳細設定") を利用し、クリックするまでこれらのオプションを隠しておくことで、メインのインターフェースをシンプルに保つことができます。この「詳細設定」セクションこそ、GPT-image-1が提供する豊富なカスタマイズオプションをユーザーに提供する場所です。 例えば、st.selectbox を使ってユーザーが画像の size (例: "1024x1024", "1792x1024") を選択できるようにしたり、st.radiost.selectboxquality ("standard", "hd") や style ("vivid", "natural") を切り替えられるように実装します。これにより、ユーザーはセクション1.2で解説したようなパラメータを直感的に操作し、より自身の意図に近い画像を生成できるようになります。

画像生成処理は完了までに時間がかかる場合があるため、ユーザーを待たせない工夫が必要です。処理実行中は st.spinner("生成中...") というメッセージを表示したり、可能であれば st.progress(value) を使って進捗状況を視覚的に示すことで、ユーザーは処理が進行中であることを理解し、安心して待つことができます。

生成された結果を表示する際には、st.image() を用います。特にimg2imgモードのように元画像と比較したい場合は、st.columns(2) を使って左右に元画像と生成画像を並べて表示すると、変更点が明確になり効果的です。

さらに、アプリケーションを初めて使うユーザーへの配慮も重要です。Streamlit 1.33以降で安定版となった st.dialog 機能を利用すれば、アプリケーションの初回起動時のみにモーダルダイアログを表示させることができます。このダイアログ内で簡単な操作説明や機能紹介を行うことで、ユーザーのオンボーディングを支援し、アプリの利用を促すことができます。

https://docs.streamlit.io/library/api-reference/dialogs/st.dialog

4.2 Entra ID 認証の実装

Azure環境でアプリケーションへのアクセスを制御するために、Microsoft Entra IDによる認証を実装します。主なアプローチは二つ考えられます。それぞれの実装方法をコード例と共に見ていきましょう。

アプローチ1: Streamlit標準OAuth機能 (st.login) を利用する

この方法は、Streamlitの組み込み機能を使って認証フローを実装します。コード自体は非常にシンプルですが、事前の設定が必要です。

まず、.streamlit/secrets.toml ファイルに、Entra IDで登録したアプリケーションの情報を記述します。

.streamlit/secrets.toml (例)
# Microsoft Entra ID OAuth設定
[microsoft]
clientId = "YOUR_ENTRA_APPLICATION_CLIENT_ID"
tenantId = "YOUR_ENTRA_TENANT_ID"
clientSecret = "YOUR_ENTRA_CLIENT_SECRET" # オプションだが推奨される場合あり
redirectUri = "http://localhost:8501" # ローカル開発用。本番環境では変更
# authorizationUrl, tokenUrl は通常自動で解決される

次に、app.py 内で st.login ボタンを表示し、ログイン後の処理を記述します。

app.py (st.login利用例)
import streamlit as st

# --- 認証処理 ---
# セッション状態にユーザー情報がない場合、ログインボタンを表示
if 'user_info' not in st.session_state:
    # "microsoft" を指定してEntra ID用のログインボタンを表示
    login_result = st.login("microsoft")

    # ログインが成功したら、返り値 (ユーザー情報) をセッション状態に保存
    if login_result:
        st.session_state.user_info = login_result
        st.rerun() # 画面を再読み込みしてログイン後の表示に切り替え
else:
    # ログイン済みの場合の処理
    user_info = st.session_state.user_info
    user_name = user_info.get("name", "不明なユーザー") # 例: name属性を取得
    user_email = user_info.get("email") # 例: email属性を取得

    st.sidebar.write(f"ようこそ、{user_name} さん")
    if user_email:
        st.sidebar.write(f"Email: {user_email}")

    if st.sidebar.button("ログアウト"):
        del st.session_state.user_info # セッションからユーザー情報を削除
        st.rerun() # 画面を再読み込みしてログイン前の表示に

    # --- ここから下に、ログイン済みユーザー向けのアプリ本体を表示 ---
    st.title("GPT-image-1 Studio (ログイン済み)")
    # ... (画像生成などの機能) ...

# アプリ本体の表示 (ログインしていない場合は表示しないなどの制御が可能)
if 'user_info' in st.session_state:
    # アプリ本体のウィジェットなどをここに記述
    pass # 例: 画像生成UIを表示
else:
    st.info("Microsoftアカウントでログインしてください。")

この方法では、ログインが成功すると st.login はユーザー情報を含む辞書などを返します (具体的な内容はプロバイダーによる)。それを st.session_state に保存し、アプリ全体でユーザーがログインしているか、誰であるかを判断します。ログアウト機能も st.session_state から情報を削除することで実装できます。このアプローチを選択する場合、Azure App Service/ACAのEasy Auth機能は必ず無効にしてください。

https://docs.streamlit.io/develop/api-reference/authentication/st.login

アプローチ2: Azure App Service / ACA の Easy Auth 機能を利用する

この方法では、認証処理の大部分をAzureプラットフォームに任せます。アプリケーションコード側では、認証済みであることを前提とし、プラットフォームが付与する情報からユーザーを特定します。

前述の通り、Streamlitでリクエストヘッダーを直接読み取る標準的な方法は提供されていません。しかし、もしAzureの構成(例: 前段のリバースプロキシがヘッダー情報を環境変数に渡すなど、特別な設定)によって X-Ms-Client-Principal ヘッダーの内容が環境変数として取得できると仮定した場合、以下のような処理でユーザー情報をデコードできます。

app.py (Easy Authヘッダー利用の概念例 - 注意点あり)
import streamlit as st
import os
import json
import base64

user_name = "ゲスト"
user_email = None
is_authenticated_by_easy_auth = False # Easy Auth経由の認証フラグ

# ★注意: Streamlit標準機能でヘッダー取得は困難なため、
#       この方法は特定の環境設定が前提となります。
# 環境変数 'HTTP_X_MS_CLIENT_PRINCIPAL' にヘッダー内容が入っていると仮定
client_principal_header_value = os.environ.get("HTTP_X_MS_CLIENT_PRINCIPAL")

if client_principal_header_value:
    try:
        # Base64デコードしてJSON文字列を取得
        decoded_principal = base64.b64decode(client_principal_header_value).decode('utf-8')
        # JSONをパースして辞書オブジェクトに変換
        principal_data = json.loads(decoded_principal)

        # claimsリストから必要な情報 (例: 名前、メールアドレス) を抽出
        claims = principal_data.get('claims', [])
        user_name = next((claim['val'] for claim in claims if claim['typ'] == 'name'), "認証済みユーザー")
        user_email = next((claim['val'] for claim in claims if claim['typ'] == 'preferred_username'), None) # メールアドレスのクレームタイプ
        is_authenticated_by_easy_auth = True # 認証情報を取得できた

        st.sidebar.write(f"ようこそ、{user_name} さん")
        if user_email:
            st.sidebar.write(f"Email: {user_email}")

    except Exception as e:
        st.warning(f"認証情報の処理中にエラーが発生しました: {e}")
        # エラー発生時はゲスト扱いなど、フォールバック処理を検討

# アプリ本体の表示制御
if is_authenticated_by_easy_auth:
    # --- ログイン済みユーザー向けのアプリ本体を表示 ---
    st.title("GPT-image-1 Studio (Easy Auth認証済み)")
    # ... (画像生成などの機能) ...
else:
    # Easy Authが有効だがヘッダーが取得できない、または認証されていない場合
    st.title("GPT-image-1 Studio")
    st.info("アクセス権限がないか、認証情報を取得できませんでした。")

このEasy Authアプローチの最大の利点は、アプリケーションコードが認証フローの詳細に関与しないことです。しかし、ユーザー情報の取得方法が環境依存になりやすいという欠点があります。一般的には、st.login を使う方がStreamlitアプリケーション内での実装は直接的で分かりやすいかもしれません。

4.3 OpenAI / Azure OpenAI SDK の利用 (2025年5月時点)

openai ライブラリ (>=1.20.0) を使って、OpenAIとAzure OpenAIの両方に対応します。クライアントの初期化は前述の通り、環境変数に基づいて行います。

app.py (クライアント初期化部分 - 再掲・要約)
from openai import AzureOpenAI, OpenAI
# ... (環境変数読み込み、エラーハンドリング)

if use_azure:
    client = AzureOpenAI(...) # Azure用初期化
    image_model_name = azure_deployment_name
else:
    client = OpenAI(...) # OpenAI用初期化
    image_model_name = "gpt-image-1"

重要: Azure OpenAIの APIバージョン (api-version)デプロイ名 (deployment_name) は、ご利用の環境に合わせて正確に設定してください。

https://learn.microsoft.com/ja-jp/azure/ai-services/openai/reference

4.4 Text to Image (txt2img) 実装

テキストプロンプトから画像を生成するには、初期化したクライアントオブジェクトの images.generate() メソッドを使用します。このメソッドには、プロンプト、モデル名(またはAzureのデプロイ名)、生成枚数 (n)、そしてセクション1.2で説明した各種カスタマイズパラメータ(size, quality, styleなど)、レスポンス形式 (response_format) を指定します。

https://platform.openai.com/docs/api-reference/images/create

app.py (txt2img呼び出し部分 - パラメータ指定例)
# StreamlitのUIでユーザーが選択した値を変数で受け取る
selected_prompt = st.text_area(...)
selected_size = st.selectbox("サイズ", ["1024x1024", "1792x1024", "1024x1792"], ...)
selected_quality = st.radio("品質", ["standard", "hd"], ...)
selected_style = st.radio("スタイル", ["vivid", "natural"], ...)

if st.button("画像を生成"):
    with st.spinner("生成中..."):
        try:
            response = client.images.generate(
                model=image_model_name,
                prompt=selected_prompt,
                n=1,
                size=selected_size,
                quality=selected_quality,
                style=selected_style,
                response_format="b64_json" # または "url"
            )
            # response_formatに応じて画像データ/URLを取得
            image_data = base64.b64decode(response.data[0].b64_json)
            st.image(image_data, caption="生成された画像")
        except Exception as e:
            st.error(f"画像生成中にエラーが発生しました: {e}")
            # エラーハンドリング

UI部分(st.selectbox, st.radioなど)でユーザーにパラメータを選択させ、その値を images.generate() に渡すことで、インタラクティブなカスタマイズ機能を実現します。

4.5 Image to Image (img2img) 実装 (2025年5月時点 - 注意点)

GPT-image-1モデルを用いたImage to Image(画像の編集やバリエーション生成)機能の実装は、特に Azure OpenAI Serviceを利用する場合、注意が必要です。2025年5月現在、Python SDKによるimg2img機能のネイティブサポートがまだ限定的、あるいはプレビュー段階である可能性が高いです。

推奨されるアプローチ:

  • OpenAI APIを利用する場合: OpenAIのPython SDK (openai>=1.0) には client.images.edit()client.images.create_variation() といったメソッドが存在します。これらのメソッドがGPT-image-1モデルで公式にサポートされているか、そして必要なパラメータ(入力画像、マスク画像、プロンプトなど)の仕様を、OpenAIの公式APIドキュメントで必ず確認してください。
  • Azure OpenAI Serviceを利用する場合:
    1. SDKの確認: まず、現在使用している openai SDKライブラリのバージョンで、AzureOpenAI クライアントオブジェクトを通じて images.edit() やそれに類するメソッドが利用可能か、また期待通りに動作するかを試します。ドキュメントやリリースノートを確認することも重要です。
    2. REST APIの利用: もしSDKが未対応、あるいは動作が不安定な場合は、Azure OpenAI Serviceの画像生成用REST APIを直接呼び出すことが、現時点では最も確実な方法となる可能性があります。これには requests ライブラリなどを使用し、適切な認証ヘッダー(api-key)を設定し、入力画像データ(および必要であればマスク画像データ)をマルチパートフォームデータ (multipart/form-data) としてPOSTリクエストで送信する必要があります。

REST APIを利用する場合、その実装は images.generate() よりも複雑になります。特に、img2img機能に対応する正確なREST APIのエンドポイントURL、必須となるリクエストパラメータ(imageパラメータの名前や形式など)、リクエストボディの構造については、実装前に必ず最新のAzure OpenAI Service REST APIリファレンスドキュメントで詳細を確認してください。

筆者のGitHubリポジトリには、その時点での最善と考えられるimg2imgの実装例が含まれている可能性がありますので、参考にしてください。

https://github.com/naoki1213mj/gpt-image-1-streamlit/blob/main/app.py

5 ローカル環境での検証

app.py と関連ファイル(.env, .streamlit/config.toml など)の準備ができたら、ローカルマシン上でアプリケーションを実行し、動作を検証します。ターミナルで仮想環境を有効にした状態で、以下のコマンドを実行します。

streamlit run app.py

実行後、ターミナルに表示されるURL(通常は http://localhost:8501)にWebブラウザでアクセスします。アプリケーションの各機能、特にAPIキーやエンドポイントを使用する画像生成・編集機能(img2imgの動作は特に注意深く)、そしてローカル用に設定した認証メカニズム(st.login など)が期待通りに動作するかを十分にテストします。問題が発生した場合は、ターミナルのログやブラウザの開発者コンソールを確認し、設定ミスやコードのエラーを修正します。

6 Docker コンテナ化

ローカルでの動作検証が完了したら、アプリケーションをDockerコンテナイメージとしてパッケージ化します。これにより、依存関係を含めてアプリケーションを隔離し、開発環境と本番環境(Azure)での動作の一貫性を確保します。

6.1 Dockerfile の作成

プロジェクトのルートディレクトリに Dockerfile を作成し、コンテナイメージをビルドするための指示を記述します。(Dockerfileの内容は前回のドラフトで提示したもので基本的に問題ありません。Pythonのベースイメージ、環境変数設定、依存関係のインストール、コードのコピー、ポートの公開、実行コマンドの指定を含みます。)

6.2 .dockerignore ファイルの作成

コンテナイメージに含めるべきでないファイルやディレクトリ(仮想環境、機密ファイル、Git関連ファイルなど)を指定するために、.dockerignore ファイルを作成します。(内容も前回のドラフトで提示したものでOKです。特に .env.streamlit/secrets.toml を除外することが重要です。)

6.3 イメージのビルドとローカルテスト

作成した Dockerfile を基に、Dockerイメージをビルドし、ローカルでコンテナを実行して最終確認を行います。

# Dockerイメージをビルド (タグ名を付けて)
# 例: gptimage1-streamlit:1.0
docker build -t gptimage1-streamlit:1.0 .

# Apple Silicon環境の場合は、Azure(AMD64)互換のイメージをビルド
# docker buildx build --platform linux/amd64 -t gptimage1-streamlit:1.0-amd64 --load .

# ビルドしたイメージからコンテナを実行 (-pでポートマッピング, --rmで自動削除)
docker run --rm -p 8501:8501 gptimage1-streamlit:1.0
# (Apple Siliconの場合は :1.0-amd64 タグのイメージを実行)

再度ブラウザで http://localhost:8501 にアクセスし、コンテナ内で実行されているアプリケーションが、ローカルで直接実行した場合と同様に動作することを確認します。

7 Azure へのデプロイ

コンテナイメージの準備ができたら、いよいよAzureへのデプロイです。Azure CLIを用いて、Azure Container Registry (ACR) にイメージをプッシュし、Azure App ServiceまたはAzure Container Apps (ACA) にデプロイします。

7.1 Azure Container Registry (ACR) の作成とイメージのプッシュ

まず、ビルドしたDockerイメージを保管するためのプライベートレジストリとしてACRを作成し、そこにイメージをプッシュします。

# (変数設定: RESOURCE_GROUP, LOCATION, ACR_NAME, IMAGE_NAME, IMAGE_TAG, FULL_IMAGE_NAME)

# リソースグループ作成 (az group create ...)
# ACR作成 (az acr create ...)
az acr create --name $ACR_NAME --resource-group $RESOURCE_GROUP --sku Basic --admin-enabled true # SKUは要件に応じて選択

# ACRにDockerログイン
az acr login --name $ACR_NAME

# ローカルイメージにACR用タグを付与
docker tag ${IMAGE_NAME}:${IMAGE_TAG} $FULL_IMAGE_NAME # AMD64イメージの場合はタグを合わせる

# ACRにイメージをプッシュ
docker push $FULL_IMAGE_NAME

これで、Azure上でコンテナイメージを利用する準備が整いました。

https://learn.microsoft.com/ja-jp/azure/container-registry/container-registry-get-started-docker-cli

7.2 デプロイ先①: App Service for Containers

Azure App Serviceは、Webアプリケーションをホストするための実績あるPaaSであり、カスタムコンテナの実行もサポートしています。

# (変数設定: APP_SERVICE_PLAN_NAME, WEB_APP_NAME)

# App Serviceプラン作成 (Linux, SKU選択)
az appservice plan create --name $APP_SERVICE_PLAN_NAME --resource-group $RESOURCE_GROUP --location $LOCATION --is-linux --sku B1

# Web App (コンテナ用) を作成し、ACRからイメージを指定してデプロイ
az webapp create --name $WEB_APP_NAME --resource-group $RESOURCE_GROUP --plan $APP_SERVICE_PLAN_NAME --deployment-container-image-name $FULL_IMAGE_NAME

# アプリケーションがリッスンするポートをApp Serviceに伝える (重要)
az webapp config appsettings set --name $WEB_APP_NAME --resource-group $RESOURCE_GROUP --settings WEBSITES_PORT=8501

# ACRからのイメージプル認証、Easy Auth、Key Vault参照設定は後続のセクションで構成します。
# (Managed Identityを使うのがベストプラクティスです)

デプロイが完了すると、https://<WEB_APP_NAME>.azurewebsites.net というURLでアプリケーションにアクセスできるようになります。

https://learn.microsoft.com/ja-jp/azure/app-service/quickstart-custom-container

7.3 デプロイ先②: Azure Container Apps (ACA)

Azure Container Appsは、サーバーレスの利便性とKubernetesベースの機能を組み合わせた、よりモダンなコンテナ実行プラットフォームです。

# (変数設定: ACA_ENV_NAME, ACA_APP_NAME)

# Container Apps Environment 作成 (アプリ実行の分離境界)
az containerapp env create --name $ACA_ENV_NAME --resource-group $RESOURCE_GROUP --location $LOCATION

# Container App を作成し、ACRイメージを指定してデプロイ
az containerapp create --name $ACA_APP_NAME --resource-group $RESOURCE_GROUP --environment $ACA_ENV_NAME \
  --image $FULL_IMAGE_NAME \
  --target-port 8501 `# コンテナのリッスンポート` \
  --ingress external `# 外部HTTP(S)アクセス許可` \
  --registry-server $ACR_NAME.azurecr.io \
  --min-replicas 0 --max-replicas 1 `# アイドル時ゼロ、最大1インスタンスのスケーリング例`

# ACRからのイメージプル認証にはManaged Identityの利用を強く推奨します。
# 1. ACAでManaged Identityを有効化 (az containerapp identity assign ...)
# 2. そのManaged IdentityにACRに対する 'AcrPull' ロールを割り当て (az role assignment create ...)
# 3. Container Appのレジストリ設定でManaged Identityを使用するよう構成
az containerapp registry set --name $ACA_APP_NAME --resource-group $RESOURCE_GROUP \
  --server $ACR_NAME.azurecr.io \
  --identity system # またはユーザー割り当てID

# Easy Auth、Key Vault参照設定は後続セクションで構成します。

ACAでは、Managed Identityを使ったACRからのイメージプルが標準的かつセキュアな方法として推奨されています。これにより、ACRの管理者パスワードなどを管理する必要がなくなります。

https://learn.microsoft.com/ja-jp/azure/container-apps/quickstart-code-to-cloud

7.4 Entra ID Easy Auth の設定 (App Service / ACA 共通)

デプロイしたアプリケーションへのアクセスを特定のユーザー(組織のメンバーなど)に限定するために、Azureプラットフォームが提供する組み込みの認証機能(Easy Auth)を使ってMicrosoft Entra ID認証を設定します。

まず、Azure PortalのMicrosoft Entra IDセクションで、このアプリケーション用の「アプリの登録」を行います。ここでアプリケーション(クライアント)IDとディレクトリ(テナント)IDが払い出されます。重要な設定として、「認証」メニューの「リダイレクトURI」に、デプロイしたアプリケーションのURLの末尾に /.auth/login/aad/callback を追加したものをプラットフォーム「Web」として登録します(例: https://<WEB_APP_NAME>.azurewebsites.net/.auth/login/aad/callback)。

次に、Azure CLIを使ってApp Service(またはACA)の認証設定を構成します。以下はApp Serviceの例です(ACAの場合は az containerapp auth microsoft updateaz containerapp auth update コマンドを使用します)。

# Entra IDアプリ登録で取得したクライアントIDとテナントIDを変数に設定
ENTRA_CLIENT_ID="YOUR_ENTRA_CLIENT_ID"
ENTRA_TENANT_ID="YOUR_ENTRA_TENANT_ID"

# App Serviceの認証設定を構成 (Microsoft Entra IDプロバイダー)
az webapp auth microsoft update --name $WEB_APP_NAME --resource-group $RESOURCE_GROUP \
  --client-id $ENTRA_CLIENT_ID \
  --tenant-id $ENTRA_TENANT_ID \
  # --client-secret YOUR_ENTRA_CLIENT_SECRET # 通常は不要。必要な場合のみ設定。
  # 発行されたトークンが有効な対象者(audience)としてアプリのURLを指定
  --allowed-token-audiences "https://${WEB_APP_NAME}.azurewebsites.net"

# 認証機能全体を有効化し、認証されていないリクエストのデフォルトアクションを
# Entra IDでのログインに設定
az webapp auth update --name $WEB_APP_NAME --resource-group $RESOURCE_GROUP \
  --enabled true \
  --action LoginWithMicrosoftEntraID \
  --default-provider MicrosoftEntraID

この設定により、アプリケーションにアクセスしようとすると、ユーザーは自動的にEntra IDのログインページにリダイレクトされ、認証成功後にアプリケーションに戻ってくるようになります。allowed-token-audiences の設定は、トークンの検証に必要なので忘れずに行いましょう。

https://learn.microsoft.com/ja-jp/azure/app-service/configure-authentication-provider-aad

7.5 Key Vault と Managed Identity によるシークレット管理

アプリケーションコードや構成ファイル内にAPIキーなどの機密情報を直接記述するのは非常に危険です。Azure Key VaultとManaged Identityを組み合わせることで、これらのシークレットを安全かつ効率的に管理できます。この方法は、現在のAzureにおけるベストプラクティスとされています。

手順の概要:

  1. Azure Key Vaultを作成し、シークレットを登録: Azure CLIやPortalを使ってKey Vaultリソースを作成し、必要なAPIキー(例: Azure OpenAI APIキー)やエンドポイントURLなどをシークレットとして登録します。
    # (変数設定: KEYVAULT_NAME)
    az keyvault create --name $KEYVAULT_NAME --resource-group $RESOURCE_GROUP --location $LOCATION
    # 例: シークレット登録 (値は環境変数などから取得)
    az keyvault secret set --vault-name $KEYVAULT_NAME --name "AoaiApiKey" --value "$YOUR_AOAI_API_KEY"
    az keyvault secret set --vault-name $KEYVAULT_NAME --name "AoaiEndpoint" --value "$YOUR_AOAI_ENDPOINT"
    
  2. App Service / ACA でManaged Identityを有効化: アプリケーションを実行するApp ServiceまたはACAのリソースに対して、システム割り当てマネージドID (System-assigned Managed Identity) またはユーザー割り当てマネージドID (User-assigned Managed Identity) を有効にします。これにより、Azure AD内にアプリケーション自身のIDが作成されます。システム割り当てIDはリソースに紐付き、リソース削除と共に削除されるため、手軽に始めるのに適しています。
    # App Serviceの場合
    az webapp identity assign --name $WEB_APP_NAME --resource-group $RESOURCE_GROUP
    # Container Appsの場合
    # az containerapp identity assign --name $ACA_APP_NAME --resource-group $RESOURCE_GROUP --system-assigned
    
    # 有効化したManaged IdentityのプリンシパルIDを取得 (後の権限付与で使用)
    APP_PRINCIPAL_ID=$(az webapp identity show --name $WEB_APP_NAME --resource-group $RESOURCE_GROUP --query principalId -o tsv)
    # (ACAの場合は az containerapp identity show ...)
    
  3. Key Vaultへのアクセス許可を設定 (RBAC推奨): 作成したアプリケーションのManaged Identity(プリンシパルID)に対して、対象のKey Vaultからシークレットを読み取る権限を付与します。Azure RBAC (ロールベースアクセス制御) を使用し、「Key Vault Secrets User」ロールを割り当てるのが推奨される方法です。
    # Managed Identity (プリンシパルID: $APP_PRINCIPAL_ID) にKey Vaultへの読み取り権限を付与
    az role assignment create --role "Key Vault Secrets User" --assignee $APP_PRINCIPAL_ID --scope "/subscriptions/$(az account show --query id -o tsv)/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.KeyVault/vaults/$KEYVAULT_NAME"
    
  4. App Service / ACA のアプリケーション設定でKey Vault参照を設定: アプリケーションが必要とする環境変数(例: AZURE_OPENAI_API_KEY)の値として、直接キーを書き込む代わりに、Key Vault内のシークレットを参照する特別な構文を使用します。
    • App Serviceの場合: @Microsoft.KeyVault(SecretUri=<シークレットのURI>) という形式を使います。
      # 参照したいシークレットのURIを取得
      AOAI_KEY_SECRET_URI=$(az keyvault secret show --vault-name $KEYVAULT_NAME --name "AoaiApiKey" --query id -o tsv)
      AOAI_ENDPOINT_SECRET_URI=$(az keyvault secret show --vault-name $KEYVAULT_NAME --name "AoaiEndpoint" --query id -o tsv)
      
      # App Serviceのアプリケーション設定でKey Vault参照を設定
      az webapp config appsettings set --name $WEB_APP_NAME --resource-group $RESOURCE_GROUP --settings \
        AZURE_OPENAI_API_KEY="@Microsoft.KeyVault(SecretUri=${AOAI_KEY_SECRET_URI})" \
        AZURE_OPENAI_ENDPOINT="@Microsoft.KeyVault(SecretUri=${AOAI_ENDPOINT_SECRET_URI})" \
        USE_AZURE_OPENAI="true" # Azure OpenAI利用フラグも忘れずに
      

https://learn.microsoft.com/ja-jp/azure/app-service/app-service-key-vault-references

*   **Container Appsの場合:** よりシンプルな `secretref:<シークレット名>` という構文と、Key Vault自体のURIを指定する環境変数(例: `KEYVAULT_URI`)を組み合わせて使用することが推奨されます(機能がGAしているか最新ドキュメントで確認)。
    ```bash
    # Key VaultのURIを取得
    KEYVAULT_URI=$(az keyvault show --name $KEYVAULT_NAME --query properties.vaultUri -o tsv)

    # Container Appsの環境変数でKey Vaultシークレットを参照
    az containerapp update --name $ACA_APP_NAME --resource-group $RESOURCE_GROUP --set-env-vars \
      AZURE_OPENAI_API_KEY=secretref:AoaiApiKey \
      AZURE_OPENAI_ENDPOINT=secretref:AoaiEndpoint \
      KEYVAULT_URI=$KEYVAULT_URI \
      USE_AZURE_OPENAI="true"
    # 注意: ACAでのsecretrefの正確な設定方法はバージョンによって変わる可能性あり
    ```

https://learn.microsoft.com/ja-jp/azure/container-apps/manage-secrets?tabs=azure-cli

  1. アプリケーションコード側の対応: 特別なコード変更は不要です。 アプリケーション (app.py) は、これまで通り os.getenv("AZURE_OPENAI_API_KEY") のように、通常の環境変数としてシークレットの値にアクセスできます。AzureプラットフォームがバックグラウンドでManaged Identityを使用し、Key Vaultから実際の値を取得して、アプリケーション起動時に環境変数として透過的に挿入してくれるためです。

この仕組みにより、機密情報をソースコードや構成ファイルから完全に分離でき、セキュリティインシデントのリスクを大幅に低減しつつ、シークレットのローテーションなどもKey Vault側で一元管理できるようになります。

8 まとめ

(2025年5月2日現在) 本記事では、Azure AIプラットフォーム上で利用可能となったGPT-image-1と、人気のUIフレームワークであるStreamlitを組み合わせ、開発初期段階からAzureへのセキュアなデプロイに至るまでの一連のプロセスを、最新の情報と筆者のサンプルコードを交えながら詳細に解説しました。

我々は、uv による高速な環境構築と Streamlit による迅速なUI開発を通じて、アイデアを効率的にプロトタイピングする手法を確認しました。特に、GPT-image-1の持つ豊富なカスタマイズオプションをStreamlitのUIでどのようにユーザーに提供できるか、その実装ポイントにも触れました。そして、Docker によるコンテナ化が、開発環境と本番環境の間のギャップを埋め、ポータビリティと再現性をいかに高めるかを見てきました。

クラウドへの展開においては、Azure Container Registry (ACR) にコンテナイメージを保管し、Azure App Service または Azure Container Apps という二つの強力なPaaSオプションへデプロイする具体的な手順を示しました。特に、ACAにおけるManaged Identityを用いたACRからのイメージプルは、よりセキュアでモダンなアプローチです。

さらに重要な点として、エンタープライズレベルのアプリケーションに不可欠なセキュリティ要件に対応するため、Microsoft Entra ID とAzureの Easy Auth 機能を連携させたユーザー認証の実装方法、そして Azure Key VaultManaged Identity を組み合わせた、コードから機密情報を完全に分離するシークレット管理のベストプラクティスを実践しました。

AIとクラウド技術は日々進化を続けています。この記事で紹介した技術要素や開発プロセス、特にAzure上でのGPT-image-1の利用方法や注意点(img2imgなど)に関する最新情報を踏まえ、皆さんが独自のAIアプリケーションを構築し、クラウドの可能性を最大限に引き出すための一助となれば、これほど嬉しいことはありません。ぜひ、提供したGitHubリポジトリのコードも活用し、さらに素晴らしいアプリケーションへと発展させていってください。

9 参考リンク (2025年5月時点更新・主要リンク再掲)

  • 本記事のサンプルコード:

https://github.com/naoki1213mj/gpt-image-1-streamlit

免責事項

本記事は情報提供を目的としており、2025年5月2日時点の情報に基づいています。本記事について、内容の正確性・完全性は保証されず、誤りを含む可能性があります。公式ドキュメントで最新情報をご確認ください。記事内のコードサンプルは自己責任でご利用ください。APIキー等の機密情報は適切に管理し、公開環境での使用時はセキュリティに十分ご注意ください。本記事内容の利用によって生じたいかなる損害(サービスの中断、データ損失、営業損失等を含む)についても、著者は一切の責任を負いません。本記事に掲載されている各社製品・サービスは各社の利用規約に従ってご利用ください。

Discussion