コンテナ・イメージの準備

ホストされたデプロイメント用のエージェント・コンテナ・イメージを準備、ビルドおよびプッシュします。

このトピックのガイドラインを使用して、Dockerイメージを準備します。

サポートされているコンテナ・イメージ・アーキテクチャ

イメージの場合、生成AIサービスは、64ビットのx86アーキテクチャ(コード名amd64)をサポートします。コンテナ・イメージを作成する場合は、プラットフォーム・タイプとしてlinux/amd64を使用します。

たとえば、

docker buildx build --platform linux/amd64 -t myimage:latest

コードの準備

ホストされたデプロイメント環境で実行するには、Dockerコンテナが次の要件を満たしている必要があります。

ホストおよびポート
  • コンテナは、ホストでリスニングする必要があります0.0.0.0
  • コンテナは、ポート8080でリスニングする必要があります
HTTPレスポンスのコンテンツ・タイプ

コンテナは、ユーザー定義パスを持つGET、PUT、POST、DELETE、PATCHなどのメソッドを使用して、RESTスタイルのリクエスト・エンドポイントとレスポンス・エンドポイントを実装するHTTPベースのサービスを公開する必要があります。

プラットフォームは、Acceptヘッダーを検査して、リクエストがストリーミング・レスポンスを予期するかどうかを決定します。

  • Acceptヘッダーにtext/event-streamが含まれている場合、エンドポイントはコンテンツ・タイプがtext/event-streamのServer-Sent Events (SSE)レスポンスを返す必要があります。
  • それ以外の場合、エンドポイントは、コンテンツ・タイプapplication/jsonの標準JSONレスポンスを返す必要があります。

この設定では、一貫性のある下位互換性のある方法で、ストリーミングと非ストリーミングの両方のやり取りのエンドポイントがサポートされます。

準備エンドポイント

Dockerコンテナは、アプリケーションが完全に初期化され、リクエストを処理する準備ができていることを確認するために、レディネス・エンドポイントを公開する必要があります。

  • パス: /ready
  • 目的:コンテナがトラフィックを受信する準備ができているかどうかを示します。
  • レスポンス形式: HTTPステータス・コードのみ
  • Content-Type: application/json
  • 成功ステータス・コード: 200 OK (アプリケーションの準備完了)

コンテナの準備ができていない場合、エンドポイントはトラフィック・ルーティングを防ぐために200以外のステータス・コードを返す必要があります。

Livenessエンドポイント

Dockerコンテナは、アプリケーションが正しく実行されており、再起動を必要としないことを確認するために、ライブ・エンドポイントを公開する必要があります。

  • パス: /health
  • 目的:コンテナが稼働中で機能しているかどうかを検出します。
  • レスポンス形式: HTTPステータス・コードのみ
  • Content-Type: application/json
  • 成功ステータス・コード: 200 OK (アプリケーションは正常です)

アプリケーションがデッドロック状態またはリカバリ不能状態になった場合、プラットフォームが自動的にコンテナを再起動できるように、エンドポイントは200以外のステータス・コードを返す必要があります。

イメージ・アーキテクチャ

このサービスはamd64をサポートしています。

ノート

Oracle Container Registryによって提供されるベース・イメージを使用することをお薦めします。そのサイトの画像は脆弱性スキャンを通過します。
予約済みの環境変数

次の環境変数は、システムで使用するために予約されています。コンテナ・コードには定義しないでください。

PORT
K_SERVICE
K_CONFIGURATION
K_REVISION
OCI_RESOURCE_PRINCIPAL_VERSION
OCI_RESOURCE_PRINCIPAL_PRIVATE_PEM
OCI_RESOURCE_PRINCIPAL_RPST
KUBERNETES_*

イメージ・アーキテクチャ

イメージは、次の例に示すように、linux/amd64プラットフォーム用に構築する必要があります。

ファイルアクセス

コンテナ・ファイル・システムは読取り専用ですが、/tmpディレクトリは書込み可能です。アプリケーションでファイルをローカルに書き込む必要がある場合は、/tmpに書き込みます。

脆弱性スキャニング

デプロイメントの前に、イメージはOCI Vulnerability Scanning Serviceを使用してスキャンされます。重大な脆弱性が検出された場合、デプロイメントは失敗します。

Oracleでは、OCIコンテナ・レジストリのベース・イメージを使用することをお薦めします。

https://container-registry.oracle.com/: イメージはすでに脆弱性スキャンを通過しています。

その他の制限事項

  • カスタム・エントリ・ポイント・コマンドはサポートされていません。CMDまたはENTRYPOINTを使用して、Dockerfileでentryコマンドを定義します。
  • ボリュームマッピングはサポートされていません。ローカル・ファイル・データは再デプロイメントまたはノードの置換時に保持されないため、コンテナはステートレスである必要があります。

サンプル・コード

次の例は、LangGraphで開発され、FastAPIでラップされた単純なエージェントを示しています。

from contextlib import asynccontextmanager
import os
import sys
from typing import Any, Dict

from dotenv import load_dotenv
from fastapi import FastAPI
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_react_agent

load_dotenv()

OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-4o-mini")
TEMPERATURE = float(os.getenv("OPENAI_TEMPERATURE", "0.7"))
OPENAI_MOCK_MODE_ENV = os.getenv("OPENAI_MOCK_MODE")
if OPENAI_MOCK_MODE_ENV is None:
    OPENAI_MOCK_MODE = not bool(OPENAI_API_KEY)
else:
    OPENAI_MOCK_MODE = OPENAI_MOCK_MODE_ENV.strip().lower() in (
        "1",
        "true",
        "yes",
        "on",
    )

app_graph = None


@asynccontextmanager
async def lifespan(app: FastAPI):
    global app_graph

    if OPENAI_MOCK_MODE and not OPENAI_API_KEY:
        print(
            "OPENAI_API_KEY is not set; running in OPENAI_MOCK_MODE.",
            file=sys.stderr,
        )
        yield
        return

    if not OPENAI_API_KEY:
        raise RuntimeError("OPENAI_API_KEY is not set in environment.")

    model = ChatOpenAI(
        model=OPENAI_MODEL,
        temperature=TEMPERATURE,
        api_key=OPENAI_API_KEY,
        streaming=True,
    )
    app_graph = create_react_agent(
        model=model,
        tools=[],
        checkpointer=MemorySaver(),
    )
    yield


app = FastAPI(lifespan=lifespan)


@app.post("/chat")
async def chat(body: Dict[str, Any]):
    thread_id = body["thread_id"]
    msg = body["message"]

    if OPENAI_MOCK_MODE and not OPENAI_API_KEY:
        return {
            "reply": f"[MOCK] OPENAI_API_KEY missing. Echo: {msg}",
            "thread_id": thread_id,
        }

    response = await app_graph.ainvoke(
        {"messages": [HumanMessage(content=msg)]},
        config={"configurable": {"thread_id": thread_id}},
    )

    if "messages" in response and response["messages"]:
        last_message = response["messages"][-1]
        ai_content = getattr(last_message, "content", str(last_message))
    else:
        ai_content = "I'm not sure how to respond to that."

    return {"reply": ai_content}


@app.get("/health")
async def health():
    return {
        "status": "Healthy",
        "mode": "mock" if (OPENAI_MOCK_MODE and not OPENAI_API_KEY) else "normal",
    }


@app.get("/ready")
async def ready():
    if OPENAI_MOCK_MODE and not OPENAI_API_KEY:
        return {"status": "Ready", "mode": "mock"}
    return {"status": "Ready"}


プロジェクト構造

project_directory/
├── agent_example.py # Your main agent code
├── pyproject.toml # Dependencies for your agent
├── Dockerfile # docker file for building image
├── uv.lock # auto generated by uv
└── __init__.py # Makes the directory a Python package

コンテナ・イメージの構築

次に、プロジェクト・ディレクトリ内のDockerファイルの例を示します。

Dockerfile
FROM python:3.11-slim

# Set working directory
WORKDIR /app

# Install uv
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv

# Copy project files
COPY pyproject.toml uv.lock ./
COPY *.py ./


# Install dependencies using uv
RUN uv sync --frozen

# Expose port
EXPOSE 8080

# Run the application using uv
CMD ["uv", "run", "python", "agent_example.py"]

amd64アーキテクチャでのDockerイメージの構築

docker buildx build --platform linux/amd64 -t my_agent:v1 .

レジストリへのイメージのプッシュ

コンテナ・登録を作成します。コンテナ・レジストリの概要を参照してください。

docker CLIを使用して、Dockerイメージをコンテナ・レジストリにプッシュします。

ステップ1: コンテナ・レジストリへのサインインコード例:

docker login kix.ocir.io

ステップ2: コンテナ・レジストリのURLおよびネームスペースを使用してイメージをタグ付けします。サンプル・コード:

docker tag my_agent:v1 ap-osaka-1.ocir.io/{your_tenancy_namespace}/my_agent:v1

ステップ3: イメージのプッシュのコード例:

docker push ap-osaka-1.ocir.io/<your_tenancy_namespace>/my_agent:v1

脆弱性のイメージのスキャン(推奨およびオプション)

イメージに含まれるオペレーティング・システム・パッケージに脆弱性があることは珍しくありません。これらの脆弱性を管理することで、システムのセキュリティ体制を強化し、新しい脆弱性が検出されたら迅速に対応できます。

スキャン・レシピおよびスキャン・ターゲットを作成するには、脆弱性のイメージのスキャンを参照してください。